【问题标题】:Why does Java Compiler refuse to compile this?为什么 Java Compiler 拒绝编译它?
【发布时间】:2012-11-09 13:06:35
【问题描述】:

为什么 Java 编译器在 finally 块中引发“局部变量 s 可能尚未初始化”。我不知道在哪个代码流中,s 仍未初始化。

 public static void test() {
    String s;
    try {
        s = "abc";
    } catch (Throwable e) {
        s = "throwable";
    } finally {
        System.out.println(s.getClass()); //---->(The local variable s may not have been initialized)
    }
}

【问题讨论】:

  • 因为局部变量还没有被初始化。
  • 如果catch分支中的代码失败了怎么办
  • 如果catch块中的赋值也失败了,那么它可能还没有被初始化

标签: java


【解决方案1】:

Java 语言规范的一部分是局部变量必须在使用前显式初始化(​​即在其值被引用之前)。

Throwables 会阻止s 被赋予一个值——OutOFMemoryError 就是其中之一。

s一个值将解决编译问题:

String s = null;

需要显式初始化的原因是局部变量使用堆栈内存,而不是像实例变量那样使用堆内存,并且没有构造阶段为变量提供默认值 - 它必须被编码。

【讨论】:

  • 是的,但我认为 OP 声明s 设置为trycatch
  • @Bohemian,显然,有 2 种可能的流程。1)正常流程:其中 a="abc"。 (2)异常流:s="throwable"。在任何一种情况下,s 都会被初始化。
  • @labbhattacharjee,(3) 双异常流:catch 块内抛出另一个异常
【解决方案2】:

如果第 6 行出现 OutOfMemory-Error,则不能在第 8 行使用。

【讨论】:

  • 在 OutOfMemory-Error 等情况下,Java 语言规范是否说明了 finally 块的执行?
  • @labbhattacharjee:JLS,第 14.20.2 节。 finally 块总是被执行,即使在 catch 块中抛出了一个新的 throwable。
  • @labbhattacharjee 是的“以确保始终恢复资源。” docs.oracle.com/javase/tutorial/essential/exceptions/…
  • @Peter:Error 是 Throwable 的子类。我故意写了 throwable,因为在 catch 块中抛出异常或错误都没有关系。 finally 块无论如何都会执行。
【解决方案3】:

这是因为编译器不能保证 100% 的 try 块中的赋值将毫无问题地运行,并且与 catch 块类似。如果两个分配都失败了,s 在不合法的finally 块中打印时仍将未初始化。

【讨论】:

    【解决方案4】:

    我不知道 s 在哪个代码流中未初始化。

    理论上,try/catch 块中可能会发生异常,例如OutOfMemoryException。为了避免这种情况,您可以使用null 初始化s

    String s = null;
    

    【讨论】:

      【解决方案5】:

      基本上,在 s 初始化之前,catch 块中可能会出现新的异常。例如 OutOfMemoryError。

      【讨论】:

        猜你喜欢
        • 2019-12-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-16
        • 2014-06-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多