局部变量可能已经被赋值

Local variable might already have been assigned

我知道有几个关于 Whosebug 的问题处理已初始化变量的问题,但我找不到任何关于局部变量的问题来回答我的问题。考虑以下摘录:

public class Test {


    public static void main() {
        final int i;

        try {
            i = computeI();
        } catch (Exception e) {
            i = 5;
        }
    }


    private static int computeI() throws Exception {
        return 3;
    }
}

java 编译器 (openjdk-8-jdk) 告诉我 i = 5 变量 i 可能已经被初始化 但无法分配 i

问题:有没有一种方法 i 可以被初始化而不知道(因为它是一个局部变量,另一个线程不能干扰我的知识).如果不是,为什么编译器会发出这个警告?

编译器没有你想的那么聪明。虽然你和我可以推断 i 可能只可能被设置在一个地方,但它没有发现这一点,因此它看到的只是对 i 的两次赋值。

您可以使用临时变量来绕过它(如我对 的回答)。

不,无法为变量赋值。然而,编译器只有有限的演绎能力(显然在这种情况下它们失败了),因此 might.

当我们有多个 catch 块时 and/or 最后,这有一定的道理。

在这种情况下,无法在执行 catch 块时初始化 i 变量,但编译器不够聪明,无法理解,它不会区分一条语句或 try 块中的多个语句。

无论如何,我更愿意使用一个简单的变量(不是常量)重写您的代码,并以这种方式在开头将其分配给默认值:

    int i = 5;

    try {
        i = computeI();
    } catch (Exception e) {
        //Exception handling 
    }

我个人的建议是:永远不要使用 try-catch 代替 if 语句和标准控制流结构。

Java 编译器遵循 Java 语言规范。

规范的以下部分回答了您的问题:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.12.4

https://docs.oracle.com/javase/specs/jls/se7/html/jls-16.html#jls-16.2.15

基本上没有规则描述您捕获的异常类型和 try 块中的赋值位置。

再想象一下,如果在 try 块中发生了错误(不会被 catch Exception 捕获),那么 i 在 try 语句之后仍将未分配。因此,即使编译器足够聪明,可以看到 i 在 catch 块中未分配 它仍然需要抱怨未分配的最终变量。

由于您尝试分配的变量是最终的。在正常流程的特定条件下,编译器不会让您将值分配给最终字段两次。但是如果您可以将其保留在条件内,编译器没有显示错误。

例如:

如果(真) 我 = 计算 I(); 别的 我 =5;