Ich möchte ein anonymous class
in ein konvertieren lambda expression
. Aber diese anonyme Klasse benutze ich das this
Schlüsselwort.
Zum Beispiel habe ich dieses einfache Observer/Observable
Muster geschrieben:
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);
}
und dieser Beispielcode mit einer anonymen Klasse (verwenden Sie das Schlüsselwort 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();
}
}
aber wenn ich es in einen Lambda-Ausdruck konvertiere:
public class Main {
public static void main(String[] args) {
Observable observable = new Observable();
observable.addObserver(notifier -> { notifier.removeObserver(this); });
observable.change();
}
}
Ich bekomme diesen Kompilierungsfehler:
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();
}
}
Der Kompilierungsfehler ist:
The method removeObserver(Main.Observer) in the type Main.Observable is not applicable for the arguments (Main)
Meine Frage lautet also: Gibt es eine Möglichkeit, auf das "Lambda-Objekt" zu verweisen this
?
observable
final
und zu übergeben ?observable
this
final Observable observable = new Observable(); observable.addObserver(notifier -> { notifier.removeObserver(observable); });
Problemumgehung 1
Ihre
change()
Methode wirftConcurrentModificationException
trotzdem.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); }
Problemumgehung 2
Ich habe das geändert
changed(Observable)
,changed(Observable, Observer)
damit ein Beobachter mit sich selbst umgehen kann.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); }
quelle
default Observer getThis(){return this;}
in Observer hinzufügen . Und verwendengetThis()
stattthis
.getThis()
Methode auf Methoden der Schnittstelle zugreifen , genauso wie er nicht auf diethis
Instanz der Klasse zugreifen kann, die die Schnittstelle implementiert.