What you have there is not a constant, it's just a static variable. To be a constant, it must be defined with the final
modifier:
private static final double PIVA=0.16;
Being a constant, its value can not be changed .
Imagine that the field is in a class with the following definition (keeping as you declare it in your example).
class ClaseConCampoEstatico {
private static double PIVA = 0.16;
public static final double getPIVA() { return PIVA; }
}
If you want to change its value, you can do it via reflection. You need to know the name of the field you want to modify and then the rest would be simple use of reflection, like this:
//obtenemos el campo que queremos modificar
//el método getDeclaredField busca en todos los campos de la clase
//sin importar su visibilidad (private, default, protected, public)
Field field = ClaseConCampoEstatico.class.getDeclaredField("PIVA");
//se define que el campo es accesible
field.setAccessible(true);
//se cambia el valor del campo
//el primer parámetro consiste del objeto sobre el cual
//se va a cambiar el valor del campo
//como se trata de un campo estático, el valor no depende de
//una variable en particular por lo que solo usamos null
//el segundo parámetro consiste del nuevo valor que tendrá el campo
field.setDouble(null, <nuevo valor>);
We will create a method to perform the example:
class ClaseConCampoEstatico {
private static double PIVA = 0.16;
public static double getPIVA() { return PIVA; }
}
public class Main {
public static void cambiaValor(double nuevoValor) {
try {
Field field = ClaseConCampoEstatico.class.getDeclaredField("PIVA");
field.setAccessible(true);
field.setDouble(null, nuevoValor);
} catch (Exception e) {
System.out.println("No se pudo cambiar el valor :(");
e.printStackTrace(System.out);
}
}
public static void main(String[] args) {
System.out.println(ClaseConCampoEstatico.getPIVA());
cambiaValor(1.0);
System.out.println(ClaseConCampoEstatico.getPIVA());
}
}
The output of the program:
0.16
1.0
However, if it were a true constant , that is, the field is marked as final
, we would see an exception:
class ClaseConCampoEstatico {
private static final double PIVA = 0.16;
public static double getPIVA() { return PIVA; }
}
//resto del código...
The output will be:
0.16
No se pudo cambiar el valor :(
java.lang.IllegalAccessException: Can not set static final double field ClaseConCampoEstatico.PIVA to (double)1.0
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:76)
at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:112)
at sun.reflect.UnsafeQualifiedStaticDoubleFieldAccessorImpl.setDouble(UnsafeQualifiedStaticDoubleFieldAccessorImpl.java:159)
at java.lang.reflect.Field.setDouble(Field.java:1060)
at Main.cambiaValor(Main.java:13)
at Main.main(Main.java:22)
0.16
Now, keep in mind that Field#setAccessible
will not always work. This is because in some execution environments, there is a SecurityManager that provides security to the application. As part of security, it prevents fields from being modified by reflection to avoid attacks. This happens for example when executing an Applet.