Java"空白最终字段可能尚未初始化"方法奇怪性抛出异常

kri*_*naz 14 java compiler-construction compiler-errors compiler-warnings

我有一些代码:

final int var1;    

if ( isSomethingTrue ) {

   var1 = 123;

} else {
   throwErrorMethod();
}

int var2 = var1;
Run Code Online (Sandbox Code Playgroud)

而throwErrorMethod的定义如下:

private void throwErrorMethod() throws Exception{

   throw new Exception();

}
Run Code Online (Sandbox Code Playgroud)

我得到了声明的blank final field may not have been initialized编译错误var2 = var1.如果我内联方法,编译就好了!

  1. 编译器是否看到throws Exception调用的方法?
  2. 为什么有一个单词的错误may会停止编译?!?

Jon*_*eet 19

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

  2. 它只是"可能",因为有一个潜在的执行路径不会初始化变量.这种执行路径的存在被定义为错误.

您可能会发现Eric Lippert 的这篇博文(第1 部分 ; 第2部分)很有趣.它是关于C#而不是Java,但它是相同的原则.

  • @Mark:是的.如果您可以告诉编译器*强制*它从未正常返回,然后在以后使用该信息,它将使某些代码位更清晰......例如此问题中的代码,可能.当前的规则很难将一个代码块提取到一个方法中,这个代码块*将永远不会正常完成,仅仅是因为影响明确赋值的方式. (2认同)

Pet*_*rey 7

例外应该是例外.它不假定总是抛出异常.

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

如果你想永远抛出异常,你可以做到

final int var1;    

if ( isSomethingTrue ) {

   var1 = 123;

} else {
   throw exceptionMethod();
}

int var2 = var1;

// later
public Exception exceptionMethod() {
    return new Exception("Complex-Exception-String");
}
Run Code Online (Sandbox Code Playgroud)