为什么 if(Boolean.TRUE) {...} 和 if(true) {...} 在 Java 中的工作方式不同
Why does if(Boolean.TRUE) {...} and if(true) {...} work differently in 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. 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
可能未分配。只做最基本的验证来帮助您。
我想知道 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. 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
可能未分配。只做最基本的验证来帮助您。