Подтвердить что ты не робот

Я нашел ошибку в Java Puzzlers VI - может кто-нибудь объяснить это?

Взгляните на это java puzzles vid от Джоша Блоха и Уильяма Пью, со временем индекс 0: 25: 00-0: 33: 00.

Один из динамиков говорит, что если вы используете строчный boolean вместо boolean, тогда LIVING будет рассматриваться как истинная "константа времени компиляции", и это уже не имеет значения, когда оно инициализируется.

Ну, это все прекрасно и денди, но посмотрите, что произойдет, когда вы вернетесь к первоначальному порядку между статическим init и конструктором, а затем выполните его с помощью простой операции "Извлечь метод". Эти две программы печатают разные выходы:

public class Elvis {
    private static final Elvis ELVIS = new Elvis();

    private Elvis () {}
    private static final boolean LIVING = true;
    private final boolean alive = LIVING;
    private final boolean lives () {return alive;}

    public static void main(String[] args) {
        System.out.println(ELVIS.lives()); // prints true
    }
}

И с рефакторизованным returnTrue() методом

public class Elvis {
    private static final Elvis ELVIS = new Elvis();

    private Elvis () {}
    private static final boolean LIVING = returnTrue();

    private static boolean returnTrue() {
        return true;
    }

    private final boolean alive = LIVING;
    private final boolean lives () {return alive;}

    public static void main(String[] args) {
        System.out.println(ELVIS.lives()); // prints false
    }
}

Почему извлечение метода returnTrue() изменяет вывод программы в этом случае?

4b9b3361

Ответ 1

Ключом к поведению, которое вы наблюдаете, является понятие "постоянная переменная". Этот оксюморон определяется в JLS 4.12.4 как переменная примитивного типа или типа String, которая является окончательной и инициализируется выражением постоянной времени компиляции. В JLS 13.1 говорится, что ссылки на постоянные поля разрешаются во время компиляции с постоянными значениями, которые они обозначают (т.е. Они встроены). Головоломка в видео полагается на то, что булеан не является ни примитивным, ни строковым. Ваш вариант основан на том факте, что вызов метода (returnTrue) в выражении не позволяет ему быть постоянным выражением времени компиляции. В любом случае, LIVING не является постоянной переменной, и программа отображает противоречивое поведение.

Головоломка 93 в Java Puzzlers ( "Class Warfare" ) связана и даже более удивительна.

Ответ 2

Во втором случае LIVING инициализируется выражением времени выполнения, поэтому он больше не является константой времени компиляции, а его значение false в момент построения ELVIS.