Lambda这个引用在java中 [英] Lambda this reference in java

查看:111
本文介绍了Lambda这个引用在java中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将匿名类转换为 lambda表达式。但是这个匿名类我使用 这个 关键字。

I want to convert an anonymous class to a lambda expression. But this anonymous class i use the this keyword.

例如,我写的这个简单的 Observer / Observable 模式:

For exemple, i wrote this simple Observer/Observable pattern :

import java.util.ArrayList;
import java.util.Collection;

public static class Observable {
    private final Collection<Observer> notifiables = new ArrayList<>();

    public Observable() { }

    public void addObserver(Observer notifiable) { notifiables.add(notifiable); }
    public void removeObserver(Observer notifiable) { notifiables.add(notifiable); }

    public void change() {
        notifiables.forEach(notifiable -> notifiable.changed(this));
    }
}

public interface Observer {
    void changed(Observable notifier);
}

此示例代码带有匿名类(使用this关键字):

and this sample code with an anonymous class (use the this keyword) :

public class Main {

    public static void main(String[] args) {
        Observable observable = new Observable();
        observable.addObserver(new Observer() {
            @Override
            public void changed(Observable notifier) {
                notifier.removeObserver(this);
            }
        });
        observable.change();
    }
}

但当我将其转换为lambda表达式时:

but when i convert it to a lambda expression :

public class Main {

    public static void main(String[] args) {
        Observable observable = new Observable();
        observable.addObserver(notifier -> { notifier.removeObserver(this); });
        observable.change();
    }
}

我收到此编译错误:

Cannot use this in a static context and in a non `static` context



public class Main {
    public void main(String[] args) {
        method();
    }

    private void method() {
        Observable observable = new Observable();
        observable.addObserver(notifier -> {
                notifier.removeObserver(this);
        });
        observable.change();
    }
}

编译错误是:

The method removeObserver(Main.Observer) in the type Main.Observable is not applicable for the arguments (Main)

所以我的问题是:有没有办法用引用lambda对象这个

So my question is : Is there a way to reference the "lambda object" with this ?

推荐答案

你不能引用这个的语义已被更改为仅在lambda中引用周围类的实例。无法从lambda内部引用lambda表达式的 this

You can't reference to this in a lambda expression. The semantic of this has been changed to reference the instance of the surrounding class only, from within the lambda. There is no way to reference to the lambda expression's this from inside the lambda.

问题在于你使用 main()方法中。 main方法是static,没有引用代表的对象

The problem is that you use this in the main() method. The main method is static and there is no reference to an object that represents this.

当你使用在您引用内部类实例的内部类的实例中。
lambda表达式不是内部类,未引用lambda表达式的实例。它引用了您定义lambda表达式的类的实例。在您的情况下,它将是Main的一个实例。但是因为你是静态方法,所以没有实例。

When you use this inside an instance of an inner class you are referencing to the instance of the inner class. A lambda expression is not an inner class, this is not referencing to the instance of the lambda expression. It is referencing to the instance of the class you define the lambda expression in. In your case it would be a instance of Main. But since your are in a static method, there is no instance.

这是你的第二个编译错误告诉你的。您将Main的实例移交给您的方法。但是你的方法签名需要一个Observer实例。

This is what your second compilation error is telling you. You hand over an instance of Main to your method. But your method signature requires an instance of Observer.

更新:

Java语言规范15.27.2说


与匿名类声明中出现的代码不同,名称的含义以及出现在lambda体中的this和super关键字,以及引用声明的可访问性,与周围上下文相同(除了lambda参数引入新名称)。

Unlike code appearing in anonymous class declarations, the meaning of names and the this and super keywords appearing in a lambda body, along with the accessibility of referenced declarations, are the same as in the surrounding context (except that lambda parameters introduce new names).

this <的透明度/ em>(显式和隐式)在lambda表达式的主体中 - 也就是说,将其视为与周围上下文相同 - 允许实现更灵活,并防止正文中非限定名称的含义依赖于重载分辨率。

The transparency of this (both explicit and implicit) in the body of a lambda expression - that is, treating it the same as in the surrounding context - allows more flexibility for implementations, and prevents the meaning of unqualified names in the body from being dependent on overload resolution.

实际上,lambda是不常见的表达式需要谈论它自己(要么递归地调用它自己还是调用它的其他方法),而更常见的是想要使用名称来引用封闭类中的东西,否则它们会被遮蔽( this,的toString()的)。如果lambda表达式需要引用它自己(就好像通过 this ),则应该使用方法引用或匿名内部类。

Practically speaking, it is unusual for a lambda expression to need to talk about itself (either to call itself recursively or to invoke its other methods), while it is more common to want to use names to refer to things in the enclosing class that would otherwise be shadowed (this, toString()). If it is necessary for a lambda expression to refer to itself (as if via this), a method reference or an anonymous inner class should be used instead.

这篇关于Lambda这个引用在java中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆