从lambda表达式引用final字段

从lambda表达式引用final字段

本文介绍了从lambda表达式引用final字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近我发现匿名类和lambda表达式之间存在细微差别:

Recently I've found a subtle difference between anonymous class and lambda expression:

public class FinalTest {
    final Runnable x = new Runnable() {
        @Override
        public void run() {
            System.out.println(x.hashCode());
        }
    };

    final Runnable y = () -> System.out.println(y.hashCode());
}

通常lambdas等同于匿名类。甚至我的Eclipse IDE都有重构将 x 转换为lambda(它变得与 y 完全相同)并转换 y 到匿名类(它变得与 x 完全相同)。然而lambda给我一个编译错误,而匿名类可以完美编译。错误消息如下所示:

Usually lambdas are equivalent to the anonymous classes. Even my Eclipse IDE has the refactoring to convert the x to lambda (it becomes exactly like y) and convert y to anonymous class (it becomes exactly like x). However the lambda gives me a compilation error while anonymous class can be perfectly compiled. The error message looks like this:

>javac FinalTest.java
FinalTest.java:9: error: self-reference in initializer
    final Runnable y = () -> System.out.println(y.hashCode());
                                                ^
1 error

所以问题是:为什么会有这样的差异?

So the question is: why there's such difference?

推荐答案

这与处理前向引用。特别是,如果使用完全限定名称,则编译(因为该规则的第三个条件变为false 在C的实例变量初始值设定项或C 的实例初始值设定项中使用是简单名称) :

This has to do with JLS #8.3.3 dealing with forward references. In particular, if you use a fully qualified name it compiles (because the third condition of that rule becomes false The use is a simple name in either an instance variable initializer of C or an instance initializer of C):

final Runnable y = () -> System.out.println(this.y.hashCode());

对于匿名类,第四个条件( C是最内层的类或封闭使用的接口不正确,因为封闭类本身就是匿名类。

In the case of the anonymous class, the fourth condition (C is the innermost class or interface enclosing the use) is not true because the enclosing class is the anonymous class itself.

这篇关于从lambda表达式引用final字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-22 19:10