Dav*_*ann 20 java lambda anonymous-inner-class
我有一个匿名的内部类和一个等效的lambda.为什么变量初始化规则对lambda更严格,是否有比匿名内部类更清晰的解决方案或在构造函数中初始化它?
import java.util.concurrent.Callable;
public class Immutable {
private final int val;
public Immutable(int val) { this.val = val; }
// Works fine
private final Callable<String> anonInnerGetValString = new Callable<String>() {
@Override
public String call() throws Exception {
return String.valueOf(val);
}
};
// Doesn't compile; "Variable 'val' might not have been initialized"
private final Callable<String> lambdaGetValString = () -> String.valueOf(val);
}
Run Code Online (Sandbox Code Playgroud)
编辑:我确实遇到了一个解决方法:使用getter for val.
Sot*_*lis 11
有关lambda表达式主体的章节说明
与出现在匿名类的声明,代码名称的含义以及
this与super在拉姆达身体出现关键词,与引用声明的可访问性一起,是同在周围的上下文(除了拉姆达参数引入新的名称).
thislambda表达式的主体(包括显式和隐式)的透明度- 也就是说,将其视为与周围上下文相同 - 允许实现更灵活,并防止正文中非限定名称的含义依赖于超载分辨率.
因此,他们更加严格.
在这种情况下,周围的上下文是对字段的赋值,而当前的问题是对表达式右侧的字段(val空白final字段)的访问.
Java语言规范说明
final当对其值进行任何访问时,每个局部变量(第14.4节)和每个空白字段(第4.12.4节,第8.3.1.2节)必须具有明确赋值.对其值的访问包括变量的简单名称(或者,对于字段,限定字段的简单名称
this),除了作为简单赋值运算符的左手操作数=(第15.26节)外,它出现在表达式的任何位置. 1).对于本地变量或空白
final字段的每次访问x,x必须在访问之前明确分配,否则发生编译时错误.
然后继续说
让我们
C成为一个类,并V成为一个空白的final非static成员字段C,声明在C.然后:
V肯定是在最左边的实例初始化器(第8.6节)或实例变量初始化器之前未分配(并且还没有明确分配)C.
V在前一个实例初始化器或实例变量初始化器之后,C在最左边的iff 之前[un]赋值的实例初始值设定项或实例变量初始V值设定项之前[un]赋值C.
你的代码基本上是这样的
private final int val;
// leftmost instance variable initializer, val still unassigned
private final Callable<String> anonInnerGetValString = ...
// still unassigned after preceding variable initializer
private final Callable<String> lambdaGetValString = ...
Run Code Online (Sandbox Code Playgroud)
因此,编译器val在初始化表达式中访问时确定未分配lambdaGetValString.
上述规则适用于使用简单名称val,而不适用于限定表达式this.val.您可以使用
final Callable<String> lambdaGetValString = () -> String.valueOf(this.val);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1277 次 |
| 最近记录: |