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

时间:2011-04-13 16:50:49

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

我有一些代码:

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. 编译器是否在名为?
  2. 的方法上看到throws Exception
  3. 如何在其中包含单词may的错误停止编译?!?

5 个答案:

答案 0 :(得分:19)

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

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

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

答案 1 :(得分: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");
}

答案 2 :(得分:1)

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

答案 3 :(得分:1)

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

} else {
   throw createErrorMethod();
}

声明createErrorMethod()返回某种Throwable。

答案 4 :(得分:0)

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