Этот ответ более чем исчерпывающий по теме.
JLS 17.5.3 Последующая модификация конечных полей
Даже тогда существует рядосложнений.Если конечное поле инициализируется константой времени компиляции в объявлении поля, изменения в последнем поле могут не наблюдаться, поскольку использование этого финального поля заменяется во время компиляции константой времени компиляции.
Но, если вы внимательно прочитаете абзац выше, вы можете найти обходной путь (установите поле private final
в конструкторе, а не в определении поля):
import java.lang.reflect.Field;
public class Test {
public static void main(String[] args) throws Exception {
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): " + f.get(pf));
}
private class WithPrivateFinalField {
private final String s;
public WithPrivateFinalField() {
this.s = "I’m totally safe";
}
public String toString() {
return "s = " + s;
}
}
}
Выходные данные выглядят следующим образом:
s = I’m totally safe
f.get(pf): I’m totally safe
s = No, you’re not!
f.get(pf): No, you’re not!
Надеюсь, это немного поможет.