为什么if(Boolean.TRUE){…}和if(true){…}在Java中的工作方式不同
我想知道if
子句中Boolean.TRUE
和true
值之间的区别。 当我使用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。执行局部变量声明 ):
[…]如果声明者没有初始化表达式, 那么每次对该变量的引用都必须先执行对该变量的赋值 ,否则§16的规则会发生编译时错误。
在这种情况下,在引用变量之前的代码中涉及if
语句,因此编译器执行一些流分析。 但是,如第16章所述。确定任务 :
除了条件布尔运算符
&&
,||
的特殊处理 ,和? :
? :
和布尔值常量表达式一样 ,在流分析中不考虑表达式的值。
所以,因为true
是一个布尔值常量表达式而且Boolean.TRUE
(它是对堆上的值的引用,受自动拆箱等影响) 是不是遵循
if (true) { x = 200; }
产生x
的明确分配
if (Boolean.TRUE) { x = 200; }
才不是。
存在差异是因为一个是真正的常数而另一个只是模仿一个。
编译器将查看if
语句之类的内容并尝试确定它们是否始终是给定的表达式( == true
, == false
, == null
等),但它只会达到某个级别。
在true
的情况下,没有歧义:它总是无疑代表“真实”。 但是, Boolean.TRUE
只是一个字段,显然不是编译器愿意去的那个字段。
public static final Boolean TRUE = new Boolean(true);
想一想如果涉及到reflection会怎么做。
当您引入额外的复杂性时,您可以清楚地看到这一点:
public static void main(String[] args) { int x; if(getCondition()) { x = 5; } System.out.println(x); } private static boolean getCondition(){ return true; }
即使表达式始终为true,编译器仍会抱怨x
可能未被赋值。 只有最基本的validation才能帮助您。
它确实抛出了这个错误,因为它不知道隐藏在Boolean.TRUE
背后的是什么。 TRUE
是布尔类中布尔类型的静态字段,但其值也可能为false
。 但事实并非如此。