Ändern private static final-Feld mit Hilfe der Java reflection
Habe ich eine Klasse mit einem private static final
Feld, dass, leider, ich muss es ändern zur Laufzeit.
Mit der spiegelung bekomme ich diesen Fehler: java.lang.IllegalAccessException: Can not set static final boolean field
Gibt es eine Möglichkeit, um den Wert zu ändern?
Field hack = WarpTransform2D.class.getDeclaredField("USE_HACK");
hack.setAccessible(true);
hack.set(null, true);
So eine schlechte Idee. Ich würde versuchen, um die Quelle und kompilieren (oder auch zu dekompilieren/kompilieren) statt.
System.ist ein public static final-Feld, kann sich aber auch geändert.
naja mein Punkt ws zu finden, ein hack in der zwischen meine app arbeiten, bis die lib verantwortlich machen, die änderung bei der nächsten Version so dass ich nicht brauchen, um hack mehr...
System.ist ein public static final-Feld, kann sich aber auch geändert.
System.out/in/err
sind so "special", dass das Java-Memory-Modell, die spezielle Erwähnung von Ihnen. Sie sind keine Beispiele, die befolgt werden sollten.naja mein Punkt ws zu finden, ein hack in der zwischen meine app arbeiten, bis die lib verantwortlich machen, die änderung bei der nächsten Version so dass ich nicht brauchen, um hack mehr...
InformationsquelleAutor fixitagain | 2010-07-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Vorausgesetzt, es ist kein
SecurityManager
ist, die dich daran hindern, dies zu tun, können SiesetAccessible
zu bekommen, umprivate
und zurücksetzen der modifier loswerdenfinal
, und tatsächlich ändernprivate static final
Feld.Hier ein Beispiel:
Vorausgesetzt, es ist kein
SecurityException
geworfen wird, wird der obige code druckt"Everything is true"
.Was eigentlich hier gemacht wird, ist wie folgt:
boolean
Wertetrue
undfalse
immain
sind autoboxed, um den Typ der ReferenzBoolean
"Konstanten"Boolean.TRUE
undBoolean.FALSE
public static final Boolean.FALSE
verweisen auf dieBoolean
bezeichnetBoolean.TRUE
false
ist autoboxed zuBoolean.FALSE
handelt es sich um das gleicheBoolean
als die einen verwiesen auf durchBoolean.TRUE
"false"
jetzt ist"true"
Fragen
static final Datei.separatorChar
für unit-TestsInteger
's cache, mutiert einString
uswVorsichtsmaßnahmen
Extremer Vorsicht sollte genommen werden, wenn Sie so etwas tun. Es kann nicht funktionieren, weil ein
SecurityManager
vorhanden sein können, aber selbst wenn es nicht klappt, je nach Nutzungsverhalten, kann es nicht funktionieren.Siehe auch
private static final boolean
, weil es inlineable als compile-time-Konstante und damit die "neue" Wert darf nicht erkennbar sein,Anhang: Über die bitweise manipulation
Im wesentlichen
schaltet das bit entsprechend
Modifier.FINAL
ausfield.getModifiers()
.&
ist die bitweise und-Verknüpfung, und~
ist der bitweisen Komplement.Siehe auch
Erinnern Konstante Ausdrücke
Immer noch nicht in der Lage, dieses Problem zu lösen?, gefallen in depression, wie ich für ihn? Funktioniert Ihr code wie folgt aussieht?
Dem Lesen der Kommentare auf diese Antwort, besonders die von @Pshemo, es erinnerte mich, dass Konstante Ausdrücke sind behandelt Verschieden, so wird es unmöglich, um es zu ändern. Daher müssen Sie ändern Sie Ihren code wie folgt Aussehen:
wenn Sie nicht der Inhaber der Klasse... ich fühle Sie!
Weitere details darüber, warum dieses Verhalten Lesen Sie diese?
es besteht kein Zweifel, dass dies ist SEHR BÖSE, aber in diesem Beispiel wurde gewählt, um das design. Meine Antwort zeigt nur, wie, in einigen Fällen ist dies möglich. Die meisten ekelhaft Beispiel, das ich denken kann, ist absichtlich gewählt, mit der Hoffnung, dass vielleicht Menschen würde sofort angewidert, indem Sie, anstatt zu fallen in der Liebe mit der Technik.
Yo, dawg. Ich hörte Sie wie Reflexion, so dachte ich auf dem Feld, so dass Sie nachdenken können, während Sie nachdenken.
Beachten Sie, dass Boolesche.FALSCH ist nicht private.Bedeutet das wirklich, die Arbeit mit "private final static" - Mitglieder?
tut es, aber Sie haben zu verwenden
getDeclaredField()
stattgetField()
für die Ziel-KlasseInformationsquelleAutor polygenelubricants
Wenn der Wert zugewiesen
static final boolean
Feld bekannt ist zur compile-Zeit, es ist ein konstant. Felder von primitiven oderString
geben können, werden compile-Zeit-Konstanten. Eine Konstante wird inline in den code, der auf den Feld. Da das Feld wird tatsächlich nicht gelesen, zur Laufzeit geändert wird, dann wird keine Wirkung haben.Den Java language specification sagt:
Hier ein Beispiel:
Wenn Sie zu dekompilieren
Checker
Sie werden sehen, dass anstelle von verweisen aufFlag.FLAG
, den code einfach schiebt einen Wert von 1 (true
) auf den Stapel (Anweisung #3).K - Nein, das bezieht sich nicht auf die JIT-Kompilierung. Die abhängige Klasse-Dateien tatsächlich enthalten die inline-Werte, und keinen Verweis auf die unabhängige Klasse. Es ist ein ziemlich einfaches experiment, um zu testen; ich will hinzufügen, ein Beispiel.
Wie funktioniert das jive mit @polygenelubricants 's Antwort-wo er definiert den Typ Boolean.falsch?--aber du hast Recht, ich habe gesehen, dass dieses Verhalten, wenn die Sachen nicht neu kompilieren, richtig.
K - in polygenlubricants " Antwort, das Feld ist nicht eine compile-Zeit-Konstante. Es ist
public static final Boolean FALSE = new Boolean(false)
nichtpublic static final boolean FALSE = false
InformationsquelleAutor erickson
Ein wenig Neugier aus der Java Language Specification, Kapitel 17, Abschnitt 17.5.4 "Write-protected-Felder":
Quelle: http://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html#jls-17.5.4
InformationsquelleAutor Stephan Markwalder
Ich auch integriert es mit joor Bibliothek
Verwenden Sie einfach
Auch ich ein Problem mit
override
denen die bisherigen Lösungen scheinen zu verpassen.Jedoch verwenden Sie dies sehr sorgfältig, nur wenn es keine andere gute Lösung.
InformationsquelleAutor iirekm
Zusammen mit top-Rankings Antwort Sie können ein bisschen einfachste Ansatz. Apache commons
FieldUtils
schon Klasse, hat eine Besondere Methode, die das tun, das Zeug. Bitte, werfen Sie einen Blick aufFieldUtils.removeFinalModifier
Methode. Sie sollten angeben, target field Instanz und Barrierefreiheit zwingt flag (wenn Sie spielen mit nicht-öffentlichen Bereichen). Mehr info finden Sie hier.Ist es? Kopieren einer Methode klingt wie eine einfachere Lösung als das importieren eine ganze Bibliothek (die das gleiche tun wie die Methode, die Sie würde kopieren).
InformationsquelleAutor nndru
Im Falle des Vorhandenseins von einem Security-Manager, den man nutzen kann
AccessController.doPrivileged
Unter dem gleichen Beispiel aus der akzeptierten Antwort oben:
Im lambda-Ausdruck,
AccessController.doPrivileged
, kann vereinfacht werden zu:InformationsquelleAutor VanagaS
Akzeptiert die Antwort war für mich bis zum Einsatz auf JDK 1.8u91.
Dann merkte ich, es konnte auf den
field.set(null, newValue);
Leitung, als ich gelesen hatte, den Wert per reflection vor dem Aufruf vonsetFinalStatic
Methode.Wohl das Lesen verursacht irgendwie anders einrichten von Java-reflection-Interna (nämlich
sun.reflect.UnsafeQualifiedStaticObjectFieldAccessorImpl
im fehlerhaften Fall stattsun.reflect.UnsafeStaticObjectFieldAccessorImpl
im Erfolgs-Fall) aber ich wollte nicht zu aufwendig es weiter.Da musste ich vorübergehend einstellen neuen Wert basierend auf den alten Wert und später den alten Wert zurück, änderte ich die Signatur etwas zu bieten-Berechnungs-Funktion extern und auch wieder Alter Wert:
Jedoch für den Allgemeinen Fall, dass dieses nicht ausreichen würde.
InformationsquelleAutor Tomáš Záluský
Wenn Ihr Feld ist einfach private Sie dies tun können:
und werfen/handle NoSuchFieldException
InformationsquelleAutor Philip Rego
Gerade gesehen, dass die Frage auf einer der interview-Frage, wenn möglich, ändern Sie die Letzte variable mit der Reflexion oder in der Laufzeit.
Mich wirklich interessiert, also das, was ich wurde, mit:
Einige einfache Klasse mit final String variable. Also in der main-Klasse
import java.lang.reflektieren.Feld;
Wird die Ausgabe wie folgt:
Gemäß der Dokumentation
https://docs.oracle.com/javase/tutorial/reflect/member/fieldValues.html
Diese Frage fragt nach einem
static
Letzte Feld, so dass dieser code nicht funktioniert.setAccessible(true)
funktioniert nur bei Einstellung Letzte Instanz-Felder.InformationsquelleAutor hasskell
Den ganzen Punkt ein
final
Feld ist, dass es nicht neu zugewiesen werden einmal eingestellt. Die JVM nutzt diese Garantie für Konsistenz in verschiedenen Orten (z.B. innere Klassen verweisen auf äußere Variablen). Also keine. In der Lage zu tun, so würde brechen die JVM!Die Lösung ist nicht zu erklären, es
final
in den ersten Platz.final
hat eine Besondere Rolle in der Multithread-Ausführung - änderungfinal
Werte brechen würde das Java-memory-Modell zu.Und ein Feld nicht deklariert
final
sollte nicht erklärt werdenstatic
.Im Allgemeinen, das ist wohl wahr, aber ich würde nicht ächten alle statische veränderliche Variablen.
Hast du überhaupt gelesen, warum singletons sind böse? Ich Tat! Jetzt weiß ich, dass Sie das böse nur in Java. Und nur, weil Sie die Verfügbarkeit von einem benutzerdefinierten class loader. Und seitdem ich weiß das alles und ich dont verwenden Sie benutzerdefinierte class loader nutze ich singletons ohne bedauern. Und so funktioniert Scala, wo singleton sind ein first-class language feature, Dass singletons böse ist, ist eine bekannte false Mythos.
Ich weiß, dass dein Kommentar ist alt, und vielleicht Ihre Ansichten haben sich mittlerweile geändert, aber ich dachte, ich würde nur hinzufügen: Singletons sind böse für Gründe, die haben nichts zu tun mit Java. Fügen Sie verborgene-Komplexität an Ihrem code. Darüber hinaus können Sie machen es unmöglich, unit-Tests, ohne auch zu wissen, dass n singletons muss auch erst konfiguriert werden. Sie sind die Antithese der dependency injection. Ihr team könnte die Entscheidung treffen, die Fallstricke der mit verborgene-Komplexität nicht überwiegt die Bequemlichkeit von Singletons, aber viele teams, die die gegenteilige Haltung aus gutem Grund.
InformationsquelleAutor thecoop