问题 为什么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
    }
}

11541
2018-02-16 16:47


起源

这毫无意义。检查真实是否属实的重点是什么? - Lawrence Aiello
@LawrenceAiello:你错过了问题的重点。在一种情况下,编译器可以正确地识别表达式总是为真,而另一种情况则不能。 - Jeroen Vannevel
它会抛出错误,但这是“值x可能尚未初始化”。那是因为在Boolean.TRUE后面也可能隐藏'false'。 - 1Darco1
也可以看看 stackoverflow.com/questions/4894311/... - Raedwald


答案:


简短的回答
对于 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;
}

才不是。


10
2018-02-16 16:50





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

编译器会查看类似的内容 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 可能是未分配的。只有最基本的验证才能帮助您。


5
2018-02-16 16:58





它确实抛出了这个错误,因为它不知道隐藏着什么 Boolean.TRUETRUE 是布尔类中布尔类型的静态字段,但其值也可以是 false。但事实并非如此。


1
2018-02-16 16:54