问题描述
|
我有一些类似的代码:
final int var1;
if ( isSomethingTrue ) {
var1 = 123;
} else {
throwErrorMethod();
}
int var2 = var1;
和throwErrorMethod定义如下:
private void throwErrorMethod() throws Exception{
throw new Exception();
}
我得到了var2 = var1
语句的blank final field may not have been initialized
编译错误。如果我内联该方法,编译就可以了!
编译器在调用的方法上看不到the4ѭ吗?
为什么其中包含单词“ 5”的错误会停止编译?!
解决方法
不,编译器无法确定
throwErrorMethod
永远不会正常完成。规范中没有任何建议。不幸的是,没有办法表明一个方法永远不会正常返回。
这只是“可以”,因为存在潜在的执行路径,该路径不会初始化变量。这样的执行路径的存在被定义为错误。
您可能会发现Eric Lippert的这两对博客帖子(第1部分;第2部分)很有趣。它是关于C#而不是Java的,但这是相同的原理。
,异常应该是例外。它不假定总是抛出异常。
编译器使用单词“ 5”,因为它无法告诉您是否可以访问未初始化的变量。此外,您可以更改该方法执行的操作而无需重新编译此类,并且所做的任何假设都将是错误的。
如果您想始终抛出异常,则可以执行
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
(必须初始化)。
,如果您想告诉编译器肯定会引发错误,但是不想内联构造错误的逻辑,则可以执行以下操作:
} else {
throw createErrorMethod();
}
其中createErrorMethod()
被声明返回某种Throwable。
,声明为“ throws Exception \”的方法不必在任何运行路径中引发此异常。因此,编译器不知道该方法是否总是会引发异常,并且还假定正常终止。因此,可能未初始化“ 12”。