익명클래스의 외부 변수에 대한 접근이 어떠한건진 기존보다 더 확실하게 알게되었습니다. 감사합니다.
근데 질문하고 싶은 내용의 일부를 제가 제대로 하지 못해서 그부분만 다시 질문을 드리겠습니다.
익명클래스와 람다식의 경우 외부 클래스 인스턴스에 참조를 같는 상황이 조금 다른거 같은데
익명클래스와 람다식 모두 외부클래스 인스턴스의 멤버 변수에 접근 및 변경에 자유롭지만
제가 작성한 예제처럼 익명클래스와 람다식은 GC에서 차이를 보였습니다. 외부클래스 인스턴스 참조를 갖는 익명클래스의 경우 익명클래스 인스턴스가 살아있는 동안 외부클래스의 인스턴스는 GC가 되지 않았고
람다식의 경우는 GC가 되었습니다.(예제처럼 외부클래스 인스턴스에 대해 어떠한 작업도 하지 않는 경우)
그래서 단설 님의 답변을 보고 람다식은 static 익명 클래스 (static inner class)가 아닐까 라는 생각에 예제를 작성해서 태스트 했는데 static 익명클래스의 경우 람다식과 마찬가지로 익명클래스의 인스턴스가 살아 있다 하더라도 외부 클래스의 인스턴스는 GC 대상이 되더라구요
그래서 람다식은 static 익명클래스와 같은 표현이다라고 적었는데 다시 생각해보니 이들은 차이가 있었습니다. 앞서 말한것처럼 람다식의 외부클래스 인스턴스의 멤버 변수에 접근 및 변경이 가능하다는 차이이죠
static 익명클래스 (static inner class)가 람다식과 같은 방식으로 동작하려면 외부클래스 인스턴스를 익명 클래스의 인스턴스가 생설될때 전달받아야 가능하겠다라는 생각을 했습니다.
여기까지가 생각을 하고 무언가 부족함을 느껴서 어제 질문을 드렸던 거구요 (그냥 막연하게 제 생각이 흐름이 맞는건지 람다식과 익명클래스의 차이 또는 람다식과 익명클래스의 차이를 좁히기 위한 방법 등 뭐든 간에 제 머릿속에 정립이 안되는 무언가에 대한 설명이 필요했습니다.)
그래서 아침에 예제를 다시 작성했는데
// static inner class
private static final class CRunnable implements Runnable {
// public WeakReference<OuterClass> ref;
// private OuterClass out;
public CRunnable(OuterClass out) {
// this.out = out;
// ref = new WeakReference<OuterClass>(out);
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
try {
System.out.println("inner class live");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
static 익명클래스 (static inner class) 인스턴스를 생성하면서 외부클래스 인스턴스를 전달을 해보았습니다. 그 결과 외부클래스 인스턴스의 참조를 갖는 익명클래스의 인스턴스가 살아있는 동안 외부클래스 인스턴스는 GC가 되지 않았습니다. 그래서 WeakReference 사용해봤는데 이번엔 GC가 되던구요
그래서 제가 내린 결론이 람다는 static 익명클래스(static inner class) 에 외부 클래스 인스턴스를 WeakReference로 가진 표현과 똑같다 입니다.
그래서 제 질문은 이게 맞는건지 입니다. 다른말로하면 람다가 컴파일 과정에서 이와 똑같이 작성이 되는건지 아니면 아예 다른 표현인건지 실제로는 어떤건지가 궁금한겁니다.
질문이 엄청 길었네요.