【问题标题】:Java "blank final field may not have been initialized" Exception thrown in method oddnessJava“空白最终字段可能尚未初始化”方法奇怪抛出异常
【发布时间】:2011-04-13 16:50:49
【问题描述】:

我有一些类似的代码:

final int var1;    

if ( isSomethingTrue ) {

   var1 = 123;

} else {
   throwErrorMethod();
}

int var2 = var1;

throwErrorMethod 的定义如下:

private void throwErrorMethod() throws Exception{

   throw new Exception();

}

我收到 blank final field may not have been initialized 编译错误 var2 = var1 语句。如果我内联方法,编译没问题!

  1. 编译器在调用的方法上没有看到throws Exception 吗?
  2. 为什么会出现包含may 字样的错误停止编译?!?

【问题讨论】:

    标签: java compiler-construction compiler-errors compiler-warnings


    【解决方案1】:
    1. 不,编译器不能确定throwErrorMethod 永远不会正常完成。规范中没有任何内容表明它应该这样做。不幸的是,没有办法表明一个方法永远不会正常返回。

    2. 这只是“可能”,因为存在未初始化变量的潜在执行路径。这种执行路径的存在被定义为错误。

    您可能会发现 Eric Lippert 的这对博文 (part 1;part 2) 很有趣。它是关于 C# 而不是 Java,但原理相同。

    【讨论】:

    • 不幸的是,没有办法表明一个方法永远不会正常返回。这真的很不幸吗?
    • @Mark:是的。如果您可以告诉编译器 enforce 它永远不会正常返回,然后稍后使用该信息,它会使某些代码更清晰......例如这个问题中的代码,可能。当前的规则很难将一段代码提取到一个方法中,而该代码块永远不会正常完成,这仅仅是因为影响明确分配的方式。
    • 我正在阅读 Eric 的博客文章。感谢您的链接。
    • 好的,完成了,我看到了价值,谢谢。虽然我大部分时间都被所有公主新娘的引用分散了注意力。
    【解决方案2】:

    异常应该是异常的。它并不假定总是抛出异常。

    编译器使用单词may,因为它无法判断您是否可以访问未初始化的变量。此外,您可以在不重新编译此类的情况下更改该方法的功能,并且它所做的任何假设都是不正确的。

    如果你想总是抛出异常,你可以这样做

    final int var1;    
    
    if ( isSomethingTrue ) {
    
       var1 = 123;
    
    } else {
       throw exceptionMethod();
    }
    
    int var2 = var1;
    
    // later
    public Exception exceptionMethod() {
        return new Exception("Complex-Exception-String");
    }
    

    【讨论】:

      【解决方案3】:

      编译器不会进行您期望的那种检查。它不能确定throwErrorMethod 实际上每次都会抛出异常。因此,它假定可以进入您的 else 子句,调用 throwErrorMethod从该方法返回,然后不初始化 var1(必须初始化)。

      【讨论】:

        【解决方案4】:

        如果你想告诉编译器肯定会抛出一个错误,但又不想内联构造错误的逻辑,你可以这样做:

        } else {
           throw createErrorMethod();
        }
        

        createErrorMethod() 被声明返回某种 Throwable。

        【讨论】:

          【解决方案5】:

          声明为“抛出异常”的方法不必在任何运行路径中抛出此异常。因此,编译器不知道该方法是否总是会抛出异常,并且也假定正常终止。因此,var1 可能未初始化。

          【讨论】:

            猜你喜欢
            • 2017-06-05
            • 2016-04-07
            • 1970-01-01
            • 2017-12-01
            • 1970-01-01
            • 2012-04-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多