Рассмотрим эти два класса:
public abstract class Bar {
protected Bar() {
System.out.println(getValue());
}
protected abstract int getValue();
}
public class Foo extends Bar {
private final int i = 20;
public Foo() {
}
@Override
protected int getValue() {
return i;
}
public static void main(String[] args) {
new Foo();
}
}
Если я выполнил Foo, выход будет равен 20.
Если я делаю поле не финальным, или если я инициализирую его в конструкторе Foo, вывод будет 0.
Мой вопрос: каков порядок инициализации в случае конечных полей и где это поведение описано в JLS?
Я ожидал найти какое-то исключительное правило о конечных полях здесь, но если я не пропущу что-то, не будет.
Обратите внимание, что я знаю, что я никогда не должен вызывать переопределяемый метод из конструктора. Это не вопрос вопроса.