局部变量可能已经被赋值
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;
我知道有几个关于 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;