int a = 1, b;
if(a > 0) b = 1;
if(a <= 0) b = 2;
System.out.println(b);
如果我这样做,我会收到:
Exception in thread "main" java.lang.Error: Unresolved compilation problem: The local variable b may not have been initialized at Broom.main(Broom.java:9)
我知道局部变量没有初始化,你有责任这样做,但在这种情况下,第一个if是不是初始化变量?
答案 0 :(得分:14)
如果您将第二个if
更改为else
,那么编译器会很高兴。
int a = 1, b;
if(a > 0) b = 1;
else b = 2;
System.out.println(b);
如果你真的想深入研究这个问题,Java语言规范的一整章专门讨论Definite Assignment的问题。这种情况与您的具体示例有关:
规则不接受变化:
void flow(boolean flag) { int k; if (flag) k = 3; if (!flag) k = 4; System.out.println(k); // k is not "definitely assigned" before here }
因此编译此程序必然会导致编译时错误。
这个特殊的例子(以及许多其他说明性的例子)似乎无视你的期望,但这正是语言设计者想要的方式,所有编译器都必须遵守规则。
答案 1 :(得分:5)
关注“IF”,编译器无法判断条件是否为真。
答案 2 :(得分:3)
如果代码甚至无法编译,请不要尝试运行代码。
通常你不能这样做,但是现代的IDE是如此“有用”,允许你这样做。它们通常会使用只会抛出错误的代码替换代码中不可编译的部分,例如您看到的错误。
更好的方法是查看编译器/ IDE为您提供的错误消息,并尝试修复之前尝试运行应用程序。
了解编译器错误和运行时异常之间的区别是一个重要的步骤。
答案 3 :(得分:2)
在Java中,必须在使用之前初始化局部变量。
在您的情况下,两个初始化都是有条件的,编译器无法确定是否有任何条件成立。这会扰乱编译器。
来自Java docs:
局部变量(§14.4,§14.13)必须在使用前通过初始化(§14.4)或赋值(§15.26)显式赋予值,其方式可由编译器使用明确分配的规则
答案 4 :(得分:1)
在编译时不会替换局部变量,因此编译器不知道 IF
是真还是假。
另一方面,如果变量定义为 final
,那么它将在编译期间被替换。
答案 5 :(得分:1)
Java编译器无法确定其他if
是否为else
。编译器很聪明但不那么聪明。
答案 6 :(得分:0)
您可以将final
关键字添加到a
的声明中,以帮助您的编译器优化代码。
// this compiles just fine
final int a = 1, b;
if(a > 0) b = 1;
if(a <= 0) b = 2;
System.out.println(b);