En supposant qu'aucun SecurityManager
vous empêche de faire cela, vous pouvez utiliser setAccessible
de contourner private
et la réinitialisation de l'indicateur pour se débarrasser de l' final
, et en fait de modifier un private static final
champ.
Voici un exemple:
import java.lang.reflect.*;
public class EverythingIsTrue {
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String args[]) throws Exception {
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
}
}
En supposant qu'aucun SecurityException
est levée, le code ci-dessus imprime "Everything is true"
.
Ce qui est fait ici est comme suit:
- La primitive
boolean
valeurs true
et false
en main
sont autoboxed de type de référence Boolean
"constantes" Boolean.TRUE
et Boolean.FALSE
- La réflexion est utilisée pour changer l'
public static final Boolean.FALSE
pour se référer à l' Boolean
visé par l' Boolean.TRUE
- En conséquence, par la suite, chaque fois qu'un
false
est autoboxed d' Boolean.FALSE
, il se réfère à la même Boolean
que celui référencé par Boolean.TRUE
- Tout ce qui a été
"false"
maintenant est - "true"
Questions connexes
Mises en garde
Un soin extrême devraient être prises, chaque fois que vous faites quelque chose comme cela. Il ne peut pas fonctionner, car SecurityManager
peut être présent, mais même si elle ne le fait pas, selon le mode d'utilisation, il peut ou peut ne pas fonctionner.
JLS 17.5.3 Modification Ultérieure de Finale Champs
Dans certains cas, tels que la désérialisation, le système aura besoin de changer l' final
les champs d'un objet après la construction. final
champs peuvent être modifiés à l'aide de la réflexion et autres dépendant de l'implémentation des moyens. Le seul modèle de ce qui est raisonnable, la sémantique est l'une dans laquelle un objet est construit, puis l' final
des champs de l'objet sont mis à jour. L'objet ne doit pas être visible pour les autres threads, ni l' final
des champs de lire, jusqu'à ce que toutes les mises à jour à l' final
des champs de l'objet sont terminées. Se fige d'un final
champ se produire à la fois à la fin du constructeur dans lequel l' final
champ est défini, et immédiatement après chaque modification d'un final
domaine par la réflexion ou l'autre mécanisme spécial.
Même alors, il ya un certain nombre de complications. Si un final
champ est initialisé à une constante de compilation dans le domaine de déclaration, de modifications à l' final
champ peut ne pas être observé, depuis les utilisations de l' final
domaine sont remplacés au moment de la compilation avec la constante de compilation.
Un autre problème est que la spécification permet agressives d'optimisation de l' final
champs. Dans un thread, il est permis de réorganiser lit d'une final
champ avec ces modifications de finale de terrain qui n'ont pas lieu dans le constructeur.
Voir aussi
-
JLS 15.28 Expression Constante
- Il est peu probable que cette technique fonctionne avec une primitive
private static final boolean
, parce que c'est inlineable comme une constante de compilation et donc le "nouveau" valeur peut ne pas être observables
Annexe: Sur le bit-à-bit de manipulation
Essentiellement,
field.getModifiers() & ~Modifier.FINAL
désactive le bit correspondant à Modifier.FINAL
de field.getModifiers()
. &
est le niveau du bit et, et ~
est le bit à bit-complément de.
Voir aussi