在方法中我有:
int x = 0
if (isA()) {
x = 1;
} else if (isB()) {
x = 2;
}
if (x != 0) {
doLater(() -> showErrorMessage(x)); // compile error here
}
// no more reference to 'x' here
我不明白为什么会产生编译错误。该错误表明x
不是最终的或有效的最终版,因此无法从lambda主体访问它。在x
调用后,doLater
没有对x
进行任何修改,因此doLater
的值实际上已经在调用x
时确定。
我猜这个问题的答案是因为if (x != 0) {
final int final_x = x;
doLater(() -> showErrorMessage(final_x));
}
没有资格被称为有效最终变量。但是,我想知道原因是什么。
编译器只能创建一个临时的最终变量,有效地使代码如下:
std::string get_name() const //note the const on member function
{
return _name; //this will work even if _name is char*, btw
}
并且一切仍然有效吗?
答案 0 :(得分:14)
有效的最终意味着它可能已成为final
,即它永远不会改变。这意味着有效的变量可以是final
。
问题在于它没有跟踪您上次更改它的时间,而是您是否更改过它。将您的if
声明更改为
int x;
if (isA()) {
x = 1;
} else if (isB()) {
x = 2;
} else {
x = 0;
}
或
int x = isA() ? 1 :
isB() ? 2 : 0;
答案 1 :(得分:3)
您的x
变量已经有效地最终被初始化一次,并且在任何情况下都不会再次更改。如果你只有:
int x = 0;
doLater(() -> showErrorMessage(x));
然后它会编译。
但是,添加可能更改变量值
的条件int x = 0;
if (isA()) {
x = 1;
} else if (isB()) {
x = 2;
}
使变量不是最终的,因此编译错误会增加。
此外,由于这个指针方法已经实现了,因此您可以将代码重构为一个简单的if-else语句:
if (isA()) {
doLater(() -> showErrorMessage(1));
} else if (isB()) {
doLater(() -> showErrorMessage(2));
}
并完全摆脱x
。
答案 2 :(得分:1)
简短版本,如果 完全>>,则无论执行哪个代码路径, 。
长版,引用Java语言规范4.12.4. final Variables(强调我的):
某些未声明为
final
的变量被视为有效最终:
现在,您可以通过删除初始化程序使其有效最终,因为它会继续:
- 如果满足以下所有条件,则声明符缺少初始值设定项的局部变量有效最终:
- 未声明
final
。- 每当它在赋值表达式中作为左侧出现时,它肯定是未赋值的,并且在赋值之前未明确赋值;也就是说,它绝对是未分配的,并且在赋值表达式的右侧(§16 (Definite Assignment))之后没有明确赋值。
- 它永远不会作为前缀或后缀的操作数增加或减少运算符。