为什么 if(Boolean.TRUE) {...} 和 if(true) {...} 在 Java 中的工作方式不同

Why does if(Boolean.TRUE) {...} and if(true) {...} work differently in Java

我想知道 if 子句中的 Boolean.TRUEtrue 值之间的区别。当我使用 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
    }
}

简答
对于 if (true) ,编译器可以推断出 x 在被读取之前已经被初始化。这不适用于 if (Boolean.TRUE) 案例。

正式回答:
所有局部变量在被读取之前必须有一个明确的赋值 (14.4.2. Execution of Local Variable Declarations):

[...] If a declarator does not have an initialization expression, then every reference to the variable must be preceded by execution of an assignment to the variable, or a compile-time error occurs by the rules of §16.

在这种情况下,引用变量之前的代码中涉及 ​​if 语句,因此编译器会执行一些流分析。但是,正如 Chapter 16. Definite Assignment 中所述:

Except for the special treatment of the conditional boolean operators &&, ||, and ? : and of boolean-valued constant expressions, the values of expressions are not taken into account in the flow analysis.

因此,由于 true 是一个布尔值 constant expression and Boolean.TRUE (which is a reference to a value on the heap, subject to auto-unboxing etc) is not,因此

if (true) {
    x = 200;
}

产生 x 的明确赋值,而

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

不会。

它确实会抛出这个错误,因为它不知道 Boolean.TRUE 后面隐藏着什么。 TRUE是class布尔中布尔类型的静态字段,但它的值也可以是false。但这并不明显。

存在差异是因为一个是真正的常量,而另一个只是模仿一个。

编译器会查看 if 语句之类的东西,并尝试弄清楚它们是否总是给定的表达式 (== true, == false, == null,等),但它只会在一定程度上做到这一点。

true 的情况下没有歧义:它总是毫无疑问地代表 "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 可能未分配。只做最基本的验证来帮助您。