【问题标题】:Why does the Java compiler complain about a local variable not having been initialized here?为什么 Java 编译器会抱怨本地变量没有在这里初始化?
【发布时间】:2011-01-22 15:29:39
【问题描述】:
int a = 1, b;
if(a > 0) b = 1;
if(a <= 0) b = 2;
System.out.println(b);

如果我运行它,我会收到:

线程“main”java.lang.Error 中的异常:未解决的编译问题: 局部变量 b 可能尚未初始化 在 Broom.main(Broom.java:9)

我知道局部变量没有初始化,你有责任这样做,但是在这种情况下,第一个 if 没有初始化变量?

【问题讨论】:

  • 因为“愚蠢”的编译器! [和语言规范。允许/强制它是]。编译器无法实现这两个条件涵盖了“a”的所有可能性 [即覆盖整个整数范围]
  • 语言规范要求这种行为。编译器是不允许聪明的。

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


【解决方案1】:

Java 编译器无法发现另一个if 作为else 工作。编译器很聪明,但没有那么聪明。

【讨论】:

  • 更具体地说,根据@polygenelubricants 的说法,它可能通过静态分析变得如此智能,但 Java 规范非常严格,在这种情况下不允许这样做。跨度>
【解决方案2】:

在 Java 中,局部变量必须在使用前进行初始化。

在您的情况下,两个初始化都是有条件的,编译器无法确定是否有任何条件为真。这会让编译器感到不安。

来自Javadocs

局部变量(第 14.4 节、第 14.13 节)必须在使用前通过初始化(第 14.4 节)或赋值(第 15.26 节)显式地赋予一个值,编译器可以使用明确分配规则

【讨论】:

    【解决方案3】:

    如果您将第二个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
    }
    

    所以编译这个程序必然会导致编译时错误。

    这个特定示例(以及许多其他说明性示例)可能看起来出乎您的意料,但这正是语言设计者想要的方式,所有编译器都必须遵守规则。

    【讨论】:

    • 除了更改为else,还可以将a更改为final以使此代码编译;编译器将优化 ifs,有效地导致除了final int a = 1, b = 1;
    【解决方案4】:

    局部变量在编译时不会被替换,所以编译器不知道 IF 是真还是假。

    另一方面,如果定义了变量final,那么它将在编译期间被替换。

    【讨论】:

      【解决方案5】:

      您可以将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);
      

      【讨论】:

        【解决方案6】:

        请不要在您的代码甚至无法编译时尝试运行它。

        通常您无论如何都无法做到这一点,但现代 IDE 非常“有用”,可以让您做到这一点。他们通常将代码中不可编译的部分替换为只会引发错误的代码,例如您看到的代码。

        更好的方法是查看编译器/IDE 提供给您的错误消息,并尝试在您尝试运行应用程序之前修复那些

        了解编译器错误和运行时异常之间的区别是一个重要的步骤。

        【讨论】:

          【解决方案7】:

          关注“IF”,编译器无法判断条件是否为真。

          【讨论】:

          • 您能否详细说明,为什么编译器无法分辨?如果将if (a &gt; 0) 替换为if (1 &gt; 0),则可以。
          • 恐怕这只是语言规范中规定的规则。有一整章专门讨论这个主题,并且关于何时明确分配/未分配变量的规则非常清楚。有些可能会违背你的直觉,但这正是设计师想要的方式。
          猜你喜欢
          • 2016-04-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-12
          • 1970-01-01
          • 2016-11-01
          • 1970-01-01
          相关资源
          最近更新 更多