因为我认为这是一个很好的编程实践,所以final如果它们只打算编写一次,我会创建所有(本地或实例)变量.
但是,我注意到当变量赋值可以抛出异常时,你不能使变量最终变为:
final int x;
try {
x = Integer.parseInt("someinput");
}
catch(NumberFormatException e) {
x = 42; // Compiler error: The final local variable x may already have been assigned
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在不诉诸临时变量的情况下做到这一点?(或者这不是最终修饰符的正确位置?)
我相信这里
final int i;
try { i = calculateIndex(); }
catch (Exception e) { i = 1; }
Run Code Online (Sandbox Code Playgroud)
i如果控制到达catch-block,则可能无法分配.但是,Java编译器不同意并声称the final local variable i may already have been assigned.
我还缺少一些细微之处,或者这只是Java语言规范用于识别潜在重新分配的模型的弱点?我的主要担心是这样的事情Thread.stop(),这可能会导致异常被"凭空捏造"抛出,但我仍然看不到它如何在赋值后抛出,这显然是try-block中的最后一个动作.
如果允许,上面的成语将使我的许多方法更简单.请注意,此用例具有一流的语言支持,例如Scala,它始终使用Maybe monad:
final int i = calculateIndex().getOrElse(1);
Run Code Online (Sandbox Code Playgroud)
我认为这个用例是一个非常好的动机,允许一个特殊情况 肯定i是在catch块中未分配.
经过一番思考后,我更加确定这只是JLS模型的一个弱点:如果我在所提出的例子中声明了公理,i当控制到达catch-block时肯定是未分配的",它将不会与任何其他公理冲突或定理.编译器i在catch块中分配之前不允许任何读取,因此i无法查看是否已分配的事实.
我有一个非常愚蠢的问题:)
例如,我有以下代码段:
class MyClass {
public static void main (String[] args) {
final String status;
try {
method1();
method2();
method3();
status = "OK";
} catch (Exception e) {
status = "BAD"; // <-- why compiler complains about this line??
}
}
public static void method1() throws Exception {
// ...
}
public static void method2() throws Exception {
// ...
}
public static void method3() throws Exception {
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
问题在于:为什么编译器抱怨这一行?
IntelliJ IDEA说,那Variable 'status' might already have …