Java lambda与匿名内部类具有不同的变量需求
我有一个匿名的内部类和一个等价的lambda。为什么lambda的变量初始化规则更严格,有没有比匿名内部类或在构造函数中初始化更干净的解决方案Java lambda与匿名内部类具有不同的变量需求,java,lambda,anonymous-inner-class,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
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);
}
import java.util.concurrent.Callable;
公共类不可变{
私人终审法院;
公共不可变(int-val){this.val=val;}
//很好
private final Callable anonInnerGetValString=new Callable(){
@凌驾
公共字符串调用()引发异常{
返回字符串.valueOf(val);
}
};
//未编译;“变量“val”可能尚未初始化”
私有最终可调用lambdaGetValString=()->String.valueOf(val);
}
编辑:我确实遇到了一个解决方法:使用getter forval
这不会编译:
public class Example
{
private final int x;
private final int y = 2 * x;
public Example() {
x = 10;
}
}
但这将:
public class Example
{
private final int x;
private final int y;
public Example() {
x = 10;
y = 2 * x;
}
}
这也将:
public class Example
{
private final int x = 10;
private final int y = 2 * x;
}
所以这与兰博达斯无关。
在同一行上初始化的字段在构造函数执行之前进行求值。
因此,此时变量“val”(或本例中的“x”)尚未初始化。有关状态的章节
与出现在匿名类声明中的代码不同,的含义
名称和出现在lambda正文中的this
和super
关键字,
除了引用声明的可访问性之外,它们都是相同的
与周围环境一样(除了lambda参数引入
新名称)
此
(显式和隐式)在
lambda表达式-即,将其与
周围环境—允许实现更大的灵活性,以及
防止正文中非限定名称的含义被忽略
取决于过载分辨率
正因为如此,他们才更加严格
在这种情况下,周围的上下文是对字段的赋值,当前的问题是访问表达式右侧的字段val
,这是一个空白的final
字段
Java语言规范说明
每个局部变量(§14.4)和每个空白final
字段(§4.12.4),
§8.3.1.2)在访问其
值出现
对其值的访问包括变量的简单名称
(或者,对于字段,由this
限定的字段的简单名称)
在表达式中的任何位置出现,但作为表达式的左操作数除外
简单赋值运算符=
(§15.26.1)
对于每次访问局部变量或空白final
字段x
,x
必须
在访问之前明确分配,否则会发生编译时错误。
然后它接着说
将C
设为类,将V
设为空final
非静态
成员字段
属于C
,在C
中声明。然后:
在最左边的实例初始值设定项(§8.6)或实例变量之前肯定未赋值(而且也没有肯定赋值)V
的初始值设定项C
在V
的实例初始值设定项或实例变量初始值设定项之前[取消]赋值,而不是在最左边的iffC
之前 [un]在前面的实例初始值设定项或实例之后分配V
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 = ...
在我的例子中,我有一个
谓词
,它试图访问一个私有final
实例变量。我还将谓词
设置为final,从而修复了它
之前-编译器错误,此.availableCities可能尚未初始化
class Service {
private final List<String> availableCities;
Service(List<String> availableCities) {
this.availableCities = availableCities;
}
private Predicate<String> isCityAvailable = city -> this.availableCities.contains(city);
}
相关:有趣的是,如果您删除
val
上的final
修饰符,当您将String.valueOf(val)
更改为String.valueOf(Immutable.this.val)
时,它会编译too@csharpfolk这个
而不是不可变的。这个
也可以用。@lucasvw我正在使用这个“在线java ide”site:,在那里,它不能仅与此
一起使用。请定义同一行。
class Service {
private final List<String> availableCities;
Service(List<String> availableCities) {
this.availableCities = availableCities;
}
private Predicate<String> isCityAvailable = city -> this.availableCities.contains(city);
}
class Service {
private final List<String> availableCities;
private final Predicate<String> isCityAvailable;
Service(List<String> availableCities) {
this.availableCities = availableCities;
this.isCityAvailable = city -> this.availableCities.contains(city);
}
}
class Service {
private final List<String> availableCities;
Service(List<String> availableCities, String topCity) {
boolean isTopCityAvailable = isCityAvailable.test(topCity); // Error: this.availableCities is not initialized yet
this.availableCities = availableCities;
}
private Predicate<String> isCityAvailable = city -> this.availableCities.contains(city);
}