Java의 Lambda이 참조
나는를 변환 할 anonymous class
A를 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);
}
익명 클래스가있는이 샘플 코드 (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();
}
}
하지만 람다 식으로 변환하면 :
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)
그래서 내 질문은 : "람다 객체"를 참조하는 방법이 this
있습니까?
this
람다 식에서 참조 할 수 없습니다 . 의 의미가 this
람다 내에서 주변 클래스의 인스턴스 만 참조하도록 변경되었습니다. 람다 this
내부에서 람다 식을 참조 할 수있는 방법이 없습니다 .
문제는 방법 this
에서 사용한다는 것 main()
입니다. 기본 메서드는 정적이며을 나타내는 개체에 대한 참조가 없습니다 this
.
this
내부 클래스의 인스턴스 내부에서 사용할 때 내부 클래스의 인스턴스를 참조하는 것입니다. 람다 식은 내부 클래스 this
가 아니며 람다 식의 인스턴스를 참조하지 않습니다. 람다 식을 정의하는 클래스의 인스턴스를 참조합니다. 귀하의 경우에는 Main의 인스턴스가 될 것입니다. 그러나 정적 메서드에 있기 때문에 인스턴스가 없습니다.
이것은 두 번째 컴파일 오류가 알려주는 것입니다. Main 인스턴스를 메서드에 넘깁니다. 그러나 메서드 서명에는 Observer 인스턴스가 필요합니다.
최신 정보:
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.
Workaround 1
Your change()
method throws ConcurrentModificationException
anyway.
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
I changed the changed(Observable)
to changed(Observable, Observer)
so that an observer can handle itself.
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);
}
참고URL : https://stackoverflow.com/questions/24202236/lambda-this-reference-in-java
'IT박스' 카테고리의 다른 글
png8과 png24의 차이점은 무엇입니까 (0) | 2020.11.28 |
---|---|
몽크 vs 몽구스 for Mongodb (0) | 2020.11.28 |
문자열에서 "¼"및 "½"과 같은 모든 분수 기호 제거 (0) | 2020.11.28 |
입력 필드가있는 메시지 상자 (0) | 2020.11.27 |
AngularJS : $ resource 요청으로 인증 토큰을 보내는 방법은 무엇입니까? (0) | 2020.11.27 |