我想将匿名类转换为lambda表达式。但是这个匿名类使用关键字this。
例如,我写了一个简单的观察者/可观察模式:
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关键字):
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表达式时:
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对象?
您的change()
方法无论如何都会抛出ConvoltModificationException
。
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);
}
我将changed(Observable)
更改为changed(Observable,observator)
,以便观察者可以处理自己。
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);
}
您不能在lambda表达式中引用this
。this
的语义已更改为仅从lambda内部引用周围类的实例。无法从lambda内部引用lambda表达式的this
。
问题是在main()
方法中使用了this
。主方法是静态的,没有对表示此的对象的引用。
当您在内部类的实例中使用此时,您引用的是内部类的实例。lambda表达式不是内部类,它不是引用lambda表达式的实例。它引用的是在其中定义lambda表达式的类的实例。在您的情况下,它将是Main的一个实例。但由于您的方法是静态的,所以没有实例。
这是您的第二个编译错误告诉您的。您将Main的一个实例移交给您的方法。但您的方法签名需要一个Observer实例。
更新:
Java语言规范15.27.2规定:
与匿名类声明中出现的代码不同,名称的含义以及lambda主体中出现的this和super关键字以及引用声明的可访问性与周围上下文中的相同(除了lambda参数引入新名称)。
lambda表达式主体中的透明性(包括显式和隐式),也就是说,将其视为与周围上下文中相同的内容,为实现提供了更大的灵活性,并防止主体中非限定名称的含义依赖于重载解析。
实际上,lambda表达式需要谈论自身(递归调用自身或调用其其他方法)是不常见的,而更常见的是希望使用名称来引用封闭类中可能会被隐藏的内容(这是toString())。如果lambda表达式需要引用自身(就像通过它一样),则应html" target="_blank">使用方法引用或匿名内部类。
我正在使用Mojang API从Minecraft玩家的用户名返回UUID。此方法在参数(我们想要知道UUID的播放器的用户名)中接受一个字符串。为了使用API的resultat,我使用SimpleJSON库(将JSON结果解析为要返回的字符串)。 我的方法抛出2个检查过的异常:IOExeption和Parse异常,因为我想要。当错误的用户名(因此不存在用户名)时,API返回一个空JSON对象,在
在我的Visual studio 2015 update 3中,当我将解决方案文件夹复制到另一台windows计算机时,我遇到了以下错误。 错误此项目引用了此计算机上缺少的NuGet包。使用NuGet包还原来下载它们。如需详细资讯,请参阅http://go.microsoft.com/fwlink/?LinkID=322105.遗失的档案是..\包\Microsoft。net . compiler
我已经检查了两个选项,允许nuget自动下载和安装丢失的包检查/打开。我也尝试删除包文件夹中的所有文件,然后让nuget重新下载它们。另外,当我打开nuget并寻找更新时,它说没有需要安装的更新。我想不出还能做什么来超越这个令人惊讶的烦人的问题。 我还通过右键单击项目并选择该选项来启用nuget还原。然后,它添加了一个nuget文件夹和该文件夹中的三个项目,并没有解决该问题。我试着重新构建,仍然得
问题内容: 希望能帮助您理解“ Java并发实践”中的以下内容: 从构造函数中调用可重写的实例方法(既不是私有方法也不是final方法)也可以使this引用转义。 这里的“转义”是否仅表示在实例完全构建之前,我们可能正在调用实例方法? 我看不到“ this”以任何其他方式逃避了实例的范围。 ‘最终’如何防止这种情况的发生?我缺少实例创建中的’最终’某些方面吗? 问题答案: 这意味着在类之外调用代码
在此代码中,我有以下警告: 用方法引用替换此lambda。 我不知道如何解决这个错误,因为它在forEach中,在map中,我可以使用,但在这里,我不能。 有什么想法吗?