Почему if (Boolean.TRUE) {...} и if (true) {...} работают по-разному в Java

Я хочу знать разницу между значениями Boolean.TRUE и true внутри предложения if. Почему это дает мне ошибку компиляции (что значение, возможно, не было инициализировано), когда я использую Boolean.TRUE вместо true.

Ниже мой код:

public class Test {

    public void method1() {
        int x;
        if(Boolean.TRUE) {
            x = 200;
        }
        System.out.println("x: " + x);   // Compilation error       
    }

    public void method2() {
        int x;
        if(true) {
            x = 200;
        }
        System.out.println("x: " + x);   // Compiles fine
    }
}

Ответ 1

Короткий ответ
Для if (true) компилятор может вывести, что x был инициализирован до его чтения. Это не выполняется для случая if (Boolean.TRUE).

Формальный ответ:
Все локальные переменные должны иметь определенное задание перед чтением (14.4.2. Выполнение локальных объявлений переменных):

[...] Если декларатор не имеет выражения инициализации, , то каждой ссылке на переменную должно предшествовать выполнение присваивания переменной, или возникает ошибка времени компиляции по правилам §16.

В этом случае существует оператор if, связанный с кодом, предшествующим ссылке на переменную, поэтому компилятор выполняет некоторый анализ потока. Однако, как указано в Глава 16. Определенное назначение:

За исключением специальной обработки условных булевых операторов &&, || и ? : и булевых значений констант, значения выражений не учитываются в анализ потока.

Так как true является булевозначным выражением и Boolean.TRUE (которое является ссылкой на значение в куче, подлежит автоматическому распаковке и т.д.) не является, следует, что

if (true) {
    x = 200;
}

дает определенное присваивание x, а

if (Boolean.TRUE) {
    x = 200;
}

нет.

Ответ 2

Разница существует, потому что одна из них является истинной константой, а другая просто имитирует ее.

Компилятор будет рассматривать такие вещи, как выражения if, и попытаться выяснить, всегда ли они будут заданным выражением (== true, == false, == null и т.д.), но это будет делать только до определенный уровень.

В случае true нет никакой двусмысленности: он всегда будет, несомненно, представлять "истину". Однако Boolean.TRUE - это просто поле, которое, по-видимому, не настолько далеко, насколько компилятор захочет пойти.

public static final Boolean TRUE = new Boolean(true);

Подумайте, например, о том, что будет сделано, если речь идет о отражении.

Это можно понять, когда вы вводите дополнительный уровень сложности:

public static void main(String[] args) {
    int x;
    if(getCondition()) {
        x = 5;
    }
    System.out.println(x);
} 

private static boolean getCondition(){
    return true;
}

Несмотря на то, что выражение всегда будет истинным, компилятор все еще жалуется, что x может быть не назначен. Только самая рудиментарная проверка сделана, чтобы помочь вам.

Ответ 3

Это делает эту ошибку, потому что она не знает, что скрывается за Boolean.TRUE. TRUE - статическое поле типа boolean в классе Boolean, но его значение также может быть false. Однако это не очевидно.