将匿名类转换为lambda后,代码的行为会有所不同

Dog*_*Dog 12 java lambda anonymous-inner-class java-8

我正在尝试重构此代码以使用lambda而不是匿名类.它是GUI中的简单项目列表.我为每个项目注册了一个不同的监听器,并且创建的最后一个项目在单击时会执行一些特殊操作.

class ItemList {
    interface OnClickListener {
        void onClick();
    }
    OnClickListener current;
    OnClickListener newListener(final int n) {
        return current = new OnClickListener() {
            public void onClick() {
                if (this == current)
                    System.out.println("doing something special (item #"+n+")");
                System.out.println("selected item #" + n);
            }
        };
    }
    public static void main(String[] args) {
        ItemList l = new ItemList();
        OnClickListener ocl1 = l.newListener(1);
        OnClickListener ocl2 = l.newListener(2);
        OnClickListener ocl3 = l.newListener(3);
        ocl1.onClick();
        ocl2.onClick();
        ocl3.onClick();
    }
}
Run Code Online (Sandbox Code Playgroud)

它按预期工作:

$ javac ItemList.java && java ItemList
selected item #1
selected item #2
doing something special (item #3)
selected item #3
Run Code Online (Sandbox Code Playgroud)

现在我将其更改为使用lambda而不是匿名类:

class ItemList {
    interface OnClickListener {
        void onClick();
    }
    OnClickListener current;
    OnClickListener newListener(final int n) {
        return current = () -> {
            if (this == current)
                System.out.println("doing something special (item #"+n+")");
            System.out.println("selected item #" + n);
        };
    }
    public static void main(String[] args) {
        ItemList l = new ItemList();
        OnClickListener ocl1 = l.newListener(1);
        OnClickListener ocl2 = l.newListener(2);
        OnClickListener ocl3 = l.newListener(3);
        ocl1.onClick();
        ocl2.onClick();
        ocl3.onClick();
    }
}
Run Code Online (Sandbox Code Playgroud)

但现在它不再对最后一项做任何特别的事情了吗?为什么?是否==与lambda表达式的工作方式不同?起初我认为这是retrolambda中的一个错误,但这个例子是在普通的JDK8上运行的,它仍然会发生.

$ javac A.java && java A
selected item #1
selected item #2
selected item #3
Run Code Online (Sandbox Code Playgroud)

Era*_*ran 13

this里面的lambda与this匿名类实例里面的含义不同.

lambda中,它指的是封闭类.

... lambda表达式不会引入新的范围.因此,您可以直接访问封闭范围的字段,方法和局部变量....要访问封闭类中的变量,请使用关键字this....

在匿名类的实例中,它引用当前对象

在实例方法或构造函数中,这是对当前对象的引用 - 正在调用其方法或构造函数的对象

这就是为什么在lambda表达式中,this == current它永远不会成立,因为它将类的实例与类型ItemList的lambda表达式进行比较OnClickListener.

  • @Dog和Eran,不,你不能用`=='来比较任何两个对象; 例如,尝试比较两个不相关的具体类的实例.但是你可以**通常比较两个引用,如果它们中的至少一个是接口,即使其中一个是"this".原因是类引用可能是实现被比较引用的接口类型的子类的实例. (3认同)