5

我在 Eclipse 报告“局部变量可能尚未初始化”错误的方式中发现了一个奇怪的二分法。如果我在 try/catch 块之外声明一个变量,在 try/catch 块内对其进行初始化,然后在 try/catch 块之后使用它,通常会发生此错误:

Random r;
try {
    r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
    e.printStackTrace();
}
r.nextInt(); //Error: The local variable r may not have been initialized

这是有道理的。我可以通过null在声明变量时初始化变量来避免错误,或者如果在 try/catch 块内发生异常,则确保程序的控制流永远不会到达下一条语句。因此,如果变量初始化失败,我真的无法继续执行,我可以这样做:

Random r;
try {
    r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
    throw new RuntimeException("Initialize secure random number generator failed");
}
r.nextInt(); //No error here

但是,我最近尝试使用System.exit来停止程序而不是 aRuntimeException来使我的程序的控制台输出更干净。我认为这些是等效的,因为两者都阻止程序继续执行,但我发现 Eclipse 不同意:

Random r;
try {
    r = new AESCounterRNG();
} catch (GeneralSecurityException e) {
    System.err.println("Couldn't initialize secure random number generator");
    System.exit(1);
}
r.nextInt(); //Error: The local variable r may not have been initialized

如果发生异常,当执行永远无法到达时,为什么 Eclipse 仍然给我“未初始化”错误r.nextInt()?这是 Eclipse 中的错误,还是有某种方式可以r.nextInt()在调用后继续执行System.exit

4

2 回答 2

5

好问题,它也困扰了我好几次。

问题在于,与抛出异常不同,仅调用方法(System.exit(1);就是这样)通常不能保证程序流停止。当然,System.exit() 的文档说这个方法永远不会正常返回。但是,虽然 的语义throw是由语言本身定义的,但 的语义System.exit()只是在 Javadocs 中。

我的猜测是他们只是懒得去实现这个特殊情况。虽然有一个涉及该主题的错误报告(https://bugs.eclipse.org/bugs/show_bug.cgi?id=126551,请参阅评论 2),但它被标记为“不会修复”,因为它似乎是太复杂。

编辑:正如 rlegendi 所指出的,这实际上是 Java 编译器的问题,而不仅仅是 Eclipse 的问题。到目前为止,我的解决方案是使用普通的 old throw, (而不是一些特殊的throw()方法),它(除了非常小的应用程序之外的任何东西)都比System.exit()无论如何都要好。

于 2012-09-22T18:40:01.243 回答
1

这不是错误:在您的第二个示例中,保证r在调用站点初始化(否则您会抛出异常,以便关闭执行分支)。

在第一个和第三个示例中,您只需执行程序代码并保持r未定义。如果您null在异常处理块或声明中分配给它,它不会抱怨。

顺便说一句,这不是 Eclipse 问题,它是由 JLS 定义的,您不能使用未初始化的变量。尝试用 Java 编译它,你应该得到完全相同的输出。

于 2012-09-22T18:28:03.973 回答