Сначала загадка: что печатает следующий код?
public class RecursiveStatic {
public static void main(String[] args) {
System.out.println(scale(5));
}
private static final long X = scale(10);
private static long scale(long value) {
return X * value;
}
}
Ответ:
0
Спойлеры ниже.
Если вы напечатаете X
в масштабе (long) и переопределите X = scale(10) + 3
, отпечатки будут X = 0
затем X = 3
. Это означает, что X
временно установлен на 0
а затем на 3
. Это нарушение final
!
Модификатор static в сочетании с модификатором final также используется для определения констант. Последний модификатор указывает, что значение этого поля не может измениться.
Источник: https://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html [выделение добавлено]
Мой вопрос: это ошибка? final
плохо определен?
Вот код, который меня интересует. X
присваивается два разных значения: 0
и 3
. Я считаю это нарушением final
.
public class RecursiveStatic {
public static void main(String[] args) {
System.out.println(scale(5));
}
private static final long X = scale(10) + 3;
private static long scale(long value) {
System.out.println("X = " + X);
return X * value;
}
}
Этот вопрос был помечен как возможный дубликат статического конечного порядка инициализации поля Java. Я считаю, что этот вопрос не является дубликатом, так как другой вопрос касается порядка инициализации, в то время как мой вопрос касается циклической инициализации в сочетании с final
тегом. Только из другого вопроса я не смог бы понять, почему код в моем вопросе не делает ошибку.
Это особенно ясно, если посмотреть на вывод, который получает Эрнесто: когда a
помечается как final
, он получает следующий вывод:
a=5
a=5
который не затрагивает основную часть моего вопроса: как final
переменная меняет свою переменную?