Сначала загадка: что печатает следующий код?
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 переменная меняет свою переменную?