Java 爪哇语;空白的最终字段可能尚未初始化";方法oddness中引发异常

Java 爪哇语;空白的最终字段可能尚未初始化";方法oddness中引发异常,java,compiler-construction,compiler-errors,compiler-warnings,Java,Compiler Construction,Compiler Errors,Compiler Warnings,我有一些代码,比如: final int var1; if ( isSomethingTrue ) { var1 = 123; } else { throwErrorMethod(); } int var2 = var1; 投掷方法的定义如下: private void throwErrorMethod() throws Exception{ throw new Exception(); } 对于var2=var1语句,我得到一个空白的最终字段可能尚未初

我有一些代码,比如:

final int var1;    

if ( isSomethingTrue ) {

   var1 = 123;

} else {
   throwErrorMethod();
}

int var2 = var1;
投掷方法的定义如下:

private void throwErrorMethod() throws Exception{

   throw new Exception();

}
对于
var2=var1
语句,我得到一个
空白的最终字段可能尚未初始化。如果我内联该方法,编译就可以了

  • 编译器没有看到调用的方法上的
    抛出异常吗
  • 为什么一个错误中有
    may
    一词会停止编译
    例外应该是例外。它并不假定总是抛出异常

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

    如果希望始终抛出异常,可以这样做

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

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

  • 不,编译器不会确定
    throwErrorMethod
    永远不会正常完成。规范中没有任何建议它应该这样做。不幸的是,没有办法表明方法永远不会正常返回

  • 它只是“may”,因为存在一个潜在的执行路径,它不会初始化变量。这种执行路径的存在被定义为错误


  • 你可能会发现Eric Lippert的这两篇博文(;)很有趣。这是关于C#而不是Java,但原理是一样的。

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

    如果您想告诉编译器肯定会抛出错误,但不想串联构造错误的逻辑,可以执行以下操作:

    } else {
       throw createErrorMethod();
    }
    

    其中
    createErrorMethod()
    被声明为返回某种类型的可丢弃对象。

    不幸的是,没有办法表明方法永远不会正常返回。那真的很不幸吗?@马克:是的。如果您可以告诉编译程序强制执行它从未正常返回,然后稍后再使用该信息,则会使某些代码更清晰。。。比如这个问题中的代码。目前的规则很难将一段永远不会正常完成的代码提取到一个方法中,这仅仅是因为这种方式会影响确定的赋值。谢谢你的链接。好的,完成了,我看到了它的价值,谢谢。虽然我大部分时间都被公主新娘的介绍分散了注意力。