【发布时间】:2016-06-02 14:48:34
【问题描述】:
考虑 Java 方法中的以下代码:
public void doWork() {
Runnable runner1 = new Runnable() {
@Override
public void run() {
System.out.println(toString());
}
};
new Thread(runner1).start();
}
当我将鼠标悬停在 new Runnable 上时,IntelliJ 会执行以下操作:
也就是说,它让我可以选择将这个 sn-p 转换为 lambda 表达式。
当我将 run() 方法更改为引用 this 时,我放弃了此功能,但是:
我想我隐约了解发生了什么(lambda 表达式范围内变量的有效终结性),但想获得有关匿名内部类和 lambda 表达式可互换性的更全面的答案。
更新后Hank D's Answer
我同意您对 this 参考分配的评估,但是
让我们看看在 IntelliJ 认为匿名内部类可以被(等效的)lambda 表达式替换的情况下程序的行为。因此,我运行了这个方法(我的外部类的名字是LambdaScope):
public void doWork() {
Runnable runner1 = new Runnable() {
@Override
public void run() {
System.out.println(toString());
}
};
new Thread(runner1).start();
}
它会产生以下输出(它显然来自这个匿名内部类从Object 继承的toString() 方法):
LambdaScope$1@7a88bb53
当我选择采用 IntelliJ 的建议并将匿名内部类转换为 lambda 表达式时,它变为:
public void doWork() {
Runnable runner1 = () -> System.out.println(toString());
new Thread(runner1).start();
}
运行此方法会产生以下结果(我已经覆盖了外部类中的方法toString()):
Outer class: class LambdaScope
我认为这是行为上的改变。那么这是一个错误吗?
这是完整的示例(您可以在 IDE 中打开它并尝试重新创建我的步骤以查看我的困惑):
public class LambdaScope {
public void doWork() {
Runnable runner1 = new Runnable() {
@Override
public void run() {
System.out.println(toString());
}
};
new Thread(runner1).start();
}
@Override
public String toString() {
return "Outer class: " + this.getClass();
}
public static void main(String[] args) {
LambdaScope ls = new LambdaScope();
ls.doWork();
}
}
【问题讨论】:
-
我用来自 JLS 的信息更新了我的答案,我希望能澄清它为什么这样做
标签: intellij-idea lambda java-8 anonymous-inner-class