gon*_*ard 63 java lambda java-8
我想把一个转换anonymous class成一个lambda expression.但这个匿名类我使用this关键字.
例如,我写了这个简单的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);
}
Run Code Online (Sandbox Code Playgroud)
这个带有匿名类的示例代码(使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
但是当我将它转换为lambda表达式时:
public class Main {
public static void main(String[] args) {
Observable observable = new Observable();
observable.addObserver(notifier -> { notifier.removeObserver(this); });
observable.change();
}
}
Run Code Online (Sandbox Code Playgroud)
我得到这个编译错误:
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();
}
}
Run Code Online (Sandbox Code Playgroud)
编译错误是:
The method removeObserver(Main.Observer) in the type Main.Observable is not applicable for the arguments (Main)
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:有没有办法引用"lambda对象" this?
Gre*_*lis 100
您无法this在lambda表达式中引用.语义this已被更改为仅从lambda内引用周围类的实例.无法this从lambda中引用lambda表达式.
问题是你this在main()方法中使用.main方法是static,没有引用表示的对象this.
当您this在内部类的实例中使用时,您将引用内部类的实例.lambda表达式不是内部类,this不引用lambda表达式的实例.它引用了您定义lambda表达式的类的实例.在您的情况下,它将是Main的一个实例.但是因为你是静态方法,所以没有实例.
这是您的第二个编译错误告诉您的.您将Main的实例移交给您的方法.但是您的方法签名需要一个Observer实例.
更新:
与出现在匿名类声明中的代码不同,名称的含义以及出现在lambda主体中的this和super关键字以及引用声明的可访问性与周围上下文中的相同(除了lambda参数引入新名称).
lambda表达式主体中的这个(显式和隐式)的透明度- 也就是说,将其视为与周围上下文相同 - 允许实现更灵活,并防止身体中不合格名称的含义依赖关于重载决议.
实际上,lambda表达式需要谈论自身(要么递归地调用自身还是调用其他方法)是不寻常的,而更常见的是想要使用名称来引用封闭类中的内容.否则被遮蔽(this,toString()).如果lambda表达式需要引用它自己(就好像通过这个),则应该使用方法引用或匿名内部类.