为什么Java编译器会抱怨本地变量未在此处初始化?

时间:2010-03-02 09:05:28

标签: java variables initialization compiler-errors variable-assignment

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是不是初始化变量?

7 个答案:

答案 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);