提问人:Grateful 提问时间:3/1/2023 更新时间:3/1/2023 访问量:117
为什么 java lambda 表达式可以使用“this”关键字引用父类成员,而匿名类不能?[复制]
Why can java lambda expressions reference parent class members using "this" keyword whereas anonymous classes can not? [duplicate]
问:
在以下课程中:
public class ThreadTest {
public static String name = "Member Accessed";
public void run() {
// Anonymous class
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Using Anonymous class, referencing this.name " + this.name);
}
};
// lambda expression
Runnable r2 = () -> {
System.out.println("Using Lambda Expression, referencing this.name " + this.name);
};
new Thread(r1).start();
new Thread(r2).start();
}
public static void main(String[] args) {
ThreadTest tt = new ThreadTest();
tt.run();
}
}
为什么 lambda 表达式可以访问 ,而匿名类不能?我知道对于匿名类,引用匿名类范围,并且不存在。但是,lambda 表达式基本上是一个匿名方法,它属于实现接口的匿名类。因此,从技术上讲,还应该引用 lambda 表达式的匿名类。但不知何故,设法引用了.this.name
this
name
this
this
name
为什么会这样?
答:
0赞
Nikolas Charalambidis
3/1/2023
#1
首先,只要引用实例而不是类变量,就可以解决这个问题:
public String name = "Member Accessed";
尽管每个 lambda 表达式都可以表示为匿名类,但它们的字节码不同,正如 Eliott Frisch 所说。我知识渊博,无法提供更多细节,但我可以向您推荐 Brian Goetz 的一篇非常有趣的读物。可悲的是,只要原始链接不再处于活动状态,就只能通过以下答案访问该脚本:Lambda 翻译策略。
无论如何,匿名类可以通过使用 指定类名来指出外部类的实例变量。this
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Using Anonymous class: " + ThreadTest.this.name);
}
};
评论
0赞
Grateful
3/1/2023
谢谢。我知道你可以从匿名的 Runnable 类中参考。但是,如果相应的 lambda 是匿名类(而不是匿名方法),那么为什么直接从 lambda 表达式工作,该表达式应该有自己的范围,因为它是一个匿名类。ThreadTest.this.name
this.name
0赞
Nikolas Charalambidis
3/1/2023
我说它们可以“表示”为匿名类,但并不是说它们是等价的,否则,它们的字节码也会相同,并且引用 through 将不起作用。我也花了一些时间来掌握这个:)this.name
0赞
Grateful
3/1/2023
谢谢你的诚实。在我看来,如果 lambda 不是匿名类,我们应该避免使用“lambda 可以表示为......”之类的词。我认为官方的预言机文档明确提到 lambda 是匿名函数......因此,让我们坚持下去。
0赞
Nikolas Charalambidis
3/1/2023
“表示为”并不意味着“等于”,但我明白你的意思。规范中没有任何地方表明 lambda 表达式是一个匿名类(这就是为什么我从不在我的答案中写 lambda 表达式“是”匿名类): docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.27 虽然,在一些 Oracle 网站上可能会出现 lambda 表达式“是”匿名类,但我还没有找到这样的页面。我绝对会选择不坚持他们是平等的。
评论
LambdaMetafactory
;Lambda 中没有匿名类。invokedynamic
invokedynamic
和方法句柄。您可能还会注意到,现在允许接口具有实现。这些天 Java 中有很多变化。default