Lambda 这个在java中的引用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24202236/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Lambda this reference in java
提问by gontard
I want to convert an anonymous class
to a lambda expression
. But this anonymous class i use the this
keyword.
我想将 an 转换anonymous class
为 a lambda expression
。但是这个匿名类我使用this
关键字。
For exemple, i wrote this simple Observer/Observable
pattern :
例如,我写了这个简单的Observer/Observable
模式:
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);
}
and this sample code with an anonymous class (use the this keyword) :
以及这个带有匿名类的示例代码(使用 this 关键字):
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();
}
}
but when i convert it to a lambda expression :
但是当我将其转换为 lambda 表达式时:
public class Main {
public static void main(String[] args) {
Observable observable = new Observable();
observable.addObserver(notifier -> { notifier.removeObserver(this); });
observable.change();
}
}
i get this compilation error :
我收到此编译错误:
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 compilation error is :
编译错误是:
The method removeObserver(Main.Observer) in the type Main.Observable is not applicable for the arguments (Main)
So my question is : Is there a way to reference the "lambda object" with this
?
所以我的问题是:有没有办法用 引用“lambda 对象” this
?
采纳答案by Gregor Koukkoullis
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.
您不能this
在 lambda 表达式中引用。的语义this
已更改为仅从 lambda 内部引用周围类的实例。无法this
从 lambda 内部引用 lambda 表达式。
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
.
问题是你this
在main()
方法中使用。main 方法是静态的,没有对表示 的对象的引用this
。
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.
当您this
在内部类的实例中使用时,您是在引用内部类的实例。lambda 表达式不是内部类,this
不引用 lambda 表达式的实例。它引用了您在其中定义 lambda 表达式的类的实例。在您的情况下,它将是 Main 的实例。但是由于您使用的是静态方法,因此没有实例。
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.
这就是你的第二个编译错误告诉你的。您将 Main 的一个实例交给您的方法。但是您的方法签名需要一个 Observer 实例。
Update:
更新:
The Java Language Specification 15.27.2 says:
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).
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.
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 主体中的 this 和 super 关键字以及引用声明的可访问性与周围上下文中的相同(除了 lambda 参数引入了新名称)。
lambda 表达式主体中的this(显式和隐式)的透明度- 即,将其与周围上下文中的处理方式相同 - 为实现提供了更大的灵活性,并防止了主体中未限定名称的含义相互依赖关于重载决议。
实际上,一个 lambda 表达式需要谈论自己(递归地调用自己或调用它的其他方法)是不寻常的,而更常见的是想要使用名称来引用封闭类中的事物否则会被隐藏(this, toString())。如果 lambda 表达式需要引用自身(就像通过this),则应改用方法引用或匿名内部类。
回答by Jin Kwon
Workaround 1
解决方法 1
Your change()
method throws ConcurrentModificationException
anyway.
你的change()
方法ConcurrentModificationException
无论如何都会抛出。
public class Main {
public static void main(String[] args) {
Observable observable = new Observable();
final Observer[] a = new Observer[1];
final Observer o = er -> er.removeObserver(a[0]); // !!
a[0] = o;
observable.addObserver(o);
observable.change();
}
}
public class Observable {
private final java.util.Collection<Observer> n
= java.util.new ArrayList<>();
public void addObserver(Observer notifiable) {
n.add(notifiable);
}
public void removeObserver(Observer notifiable) {
n.add(notifiable);
}
public void change() {
for (final Observer o : n.toArray(new Observer[n.size()])) {
o.changed(this);
}
}
}
public interface Observer {
void changed(Observable notifier);
}
Workaround 2
解决方法 2
I changed the changed(Observable)
to changed(Observable, Observer)
so that an observer can handle itself.
我将 更改changed(Observable)
为changed(Observable, Observer)
以便观察者可以处理自己。
public class Main {
public static void main(String[] args) {
Observable observable = new Observable();
final Observer o = (er, ee) -> er.removeObserver(ee); // !!
observable.addObserver(o);
observable.change();
}
}
public class Observable {
private final java.util.Collection<Observer> n
= new java.util.ArrayList<>();
public void addObserver(Observer notifiable) {
n.add(notifiable);
}
public void removeObserver(Observer notifiable) {
n.add(notifiable);
}
public void change() {
for (final Observer o : n.toArray(new Observer[n.size()])) {
o.changed(this, o);
}
}
}
public interface Observer {
void changed(Observable notifier, Observer notifiee);
}