Suponiendo que no SecurityManager
te impide hacer esto, puedes usarlo setAccessible
para desplazarte private
y restablecer el modificador para deshacerte de él final
y, de hecho, modificar un private static final
campo.
Aquí hay un ejemplo:
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"
}
}
Asumiendo que no SecurityException
se lanza, se imprime el código anterior "Everything is true"
.
Lo que realmente se hace aquí es lo siguiente:
- Los
boolean
valores primitivos true
y false
en main
se autoboxing al tipo de referencia Boolean
"constantes" Boolean.TRUE
yBoolean.FALSE
- La reflexión se utiliza para cambiar la
public static final Boolean.FALSE
referencia a la Boolean
referencia deBoolean.TRUE
- Como resultado, posteriormente cada vez que un
false
se autoboxed a Boolean.FALSE
, se refiere a la misma Boolean
como el referido a porBoolean.TRUE
- Todo lo que era
"false"
ahora es"true"
Preguntas relacionadas
Advertencias
Se debe tener mucho cuidado cuando haga algo como esto. Es posible que no funcione porque SecurityManager
puede estar presente, pero incluso si no lo hace, dependiendo del patrón de uso, puede funcionar o no.
JLS 17.5.3 Modificación posterior de campos finales
En algunos casos, como la deserialización, el sistema necesitará cambiar los final
campos de un objeto después de la construcción. final
los campos se pueden cambiar a través de la reflexión y otros medios dependientes de la implementación. El único patrón en el que esto tiene una semántica razonable es uno en el que se construye un objeto y luego final
se actualizan los campos del objeto. El objeto no debe hacerse visible para otros subprocesos, ni deben final
leerse los campos, hasta que final
se completen todas las actualizaciones de los campos del objeto. Las congelaciones de un final
campo se producen tanto al final del constructor en el que final
se establece el campo como inmediatamente después de cada modificación de un final
campo a través de la reflexión u otro mecanismo especial.
Incluso entonces, hay una serie de complicaciones. Si un final
campo se inicializa a una constante de tiempo de compilación en la declaración de campo, es final
posible que no se observen cambios en el campo, ya que los usos de ese final
campo se reemplazan en tiempo de compilación con la constante de tiempo de compilación.
Otro problema es que la especificación permite una optimización agresiva de los final
campos. Dentro de un hilo, está permitido reordenar las lecturas de un final
campo con las modificaciones de un campo final que no tienen lugar en el constructor.
Ver también
- JLS 15.28 Expresión constante
- Es poco probable que esta técnica funcione con una primitiva
private static final boolean
, porque es inlineable como una constante de tiempo de compilación y, por lo tanto, el valor "nuevo" puede no ser observable
Apéndice: sobre la manipulación bit a bit
Esencialmente,
field.getModifiers() & ~Modifier.FINAL
apaga el bit correspondiente a Modifier.FINAL
from field.getModifiers()
. &
es el bit a bit y ~
el complemento a bit.
Ver también
Recuerda expresiones constantes
¿Aún no puedes resolver esto ?, ¿has caído en la depresión como lo hice yo? ¿Su código se ve así?
public class A {
private final String myVar = "Some Value";
}
Al leer los comentarios sobre esta respuesta, especialmente la de @Pshemo, me recordó que las expresiones constantes se manejan de manera diferente, por lo que será imposible modificarla. Por lo tanto, deberá cambiar su código para que se vea así:
public class A {
private final String myVar;
private A() {
myVar = "Some Value";
}
}
si no eres el dueño de la clase ... te siento!
Para más detalles sobre por qué este comportamiento lee esto ?