Ändern privater Endfelder durch Reflektion
class WithPrivateFinalField {
private final String s = "I’m totally safe";
public String toString() {
return "s = " + s;
}
}
WithPrivateFinalField pf = new WithPrivateFinalField();
System.out.println(pf);
Field f = pf.getClass().getDeclaredField("s");
f.setAccessible(true);
System.out.println("f.get(pf): " + f.get(pf));
f.set(pf, "No, you’re not!");
System.out.println(pf);
System.out.println(f.get(pf));
Ausgabe:
s = I’m totally safe
f.get(pf): I’m totally safe
s = I’m totally safe
No, you’re not!
Warum funktioniert es auf diese Weise, können Sie bitte erklären? Die erste print-sagt uns, dass die privaten "s" - Feld nicht geändert wurde, als ich erwarte. Wenn wir aber das Feld per reflection, die zweite Auflage zeigt, ist es aktualisiert.
InformationsquelleAutor der Frage Alexandr | 2010-12-23
Du musst angemeldet sein, um einen Kommentar abzugeben.
Diese Antwort ist mehr als erschöpfend auf das Thema.
JLS 17.5.3 Nachträgliche Änderungen der Definitiven Felder
Aber, wenn Sie Lesen über sehr sorgfältig, können Sie einen Weg finden, um hier (
private final
Feld im Konstruktor statt in der Feld-definition):Die Ausgabe ist dann wie folgt:
Hoffe, das hilft ein bisschen.
InformationsquelleAutor der Antwort Jiri Patera
Diese
wirklich kompiliert wie diese:
Ist, compile-Zeit-Konstanten bekommen inlined. Sehen diese Frage. Der einfachste Weg, um zu vermeiden inlining ist zu erklären, dass die
String
wie diese:Für andere Arten, eine triviale Methode aufrufen, funktioniert der trick:
InformationsquelleAutor der Antwort Joonas Pulakka
Hier ein dekompilieren der
WithPrivateFinalField
class-Datei (ich habe es in einer separaten Klasse, für die Einfachheit):Hinweis: in der
toString()
Methode, die Konstante verwendet, bei Adresse 0 [0 ldc <String "s = I’m totally safe"> [23]
] zeigt der compiler bereits verkettet die Zeichenfolge literal"s = "
und die private final Feld" I’m totally safe"
zusammen im Voraus und gespeichert. Die toString () - Methode wird immer wieder"s = I’m totally safe"
unabhängig davon, wie die Instanz-variables
änderungen.InformationsquelleAutor der Antwort Bert F
Wird
final
der compiler erwartet, dass der Wert nicht zu ändern, so dass es wahrscheinlich hardcoded string direkt in IhretoString
Methode.InformationsquelleAutor der Antwort Gabe