인프런 커뮤니티 질문&답변

정권호님의 프로필 이미지
정권호

작성한 질문수

이펙티브 자바 완벽 공략 1부

아이템 7. 완벽 공략 20 - WeakHashMap

PhantomReference 가 소멸되는 시점을 보는 코드 부분이 약간 이상한것 같습니다.

작성

·

440

0

public class PhantomReferenceExample {

    public static void main(String[] args) throws InterruptedException {
        BigObject strong = new BigObject();
        ReferenceQueue<BigObject> rq = new ReferenceQueue<>();

        BigObjectReference<BigObject> phantom = new BigObjectReference<>(strong, rq);
        strong = null;

        System.gc();
        Thread.sleep(3000L);

        // TODO 팬텀은 유령이니까..
        //  죽었지만.. 사라지진 않고 큐에 들어갑니다.
        System.out.println(phantom.isEnqueued());

        Reference<? extends BigObject> reference = rq.poll();
        BigObjectReference bigObjectCleaner = (BigObjectReference) reference;
        bigObjectCleaner.cleanUp();
        reference.clear();
    }
}

위에 코드에서 커스텀하게 만든 BigObjectReference 로 형변환을 하고 cleanUp을 따로 호출 하는 부분이 이해가 잘 가지 않습니다.

cleanUp 메서드도 단순히 출력만하는데

굳이나 상속을 받아서 커스텀하게 만든 형태가 만든게 무의미한 것 같습니다.

 

기선님이 의도한 소멸되는 시점을 확인하고자 하면 아마 아래와 같이 clear 메서드를 오버라이딩하는게 좀 더 맞지 않나 조심 스럽게 의견을 내봅니다.

public class BigObjectReference<BigObject> extends PhantomReference<BigObject> {
	public BigObjectReference(BigObject referent, ReferenceQueue<? super BigObject> q) {
		super(referent, q);
	}

	@Override
	public void clear() {
		super.clear();
                System.out.println("clean up");
	}
}
public class PhantomReferenceExample {

	public static void main(String[] args) throws InterruptedException {
		BigObject strong = new BigObject();
		ReferenceQueue<BigObject> rq = new ReferenceQueue<>();

		BigObjectReference<BigObject> phantom = new BigObjectReference<>(strong, rq);
		strong = null;

		System.gc();
		Thread.sleep(3000L);

		// TODO 팬텀은 유령이니까..
		//  죽었지만.. 사라지진 않고 큐에 들어갑니다.
		System.out.println(phantom.isEnqueued());

		Reference<? extends BigObject> reference = rq.poll();
		reference.clear();
	}
}

 

출력화면

 

답변 1

0

안녕하세요, 인프런 AI 인턴이에요.

코드를 보면 BigObjectReference 클래스에서 clear 메서드를 오버라이딩하여 cleanUp 메서드를 호출하는데, 이는 상속 받은 PhantomReference 클래스의 clear 메서드가 호출된 뒤에 수행됩니다. 따라서 clear 메서드를 오버라이딩하여 바로 출력을 하면, PhantomReference의 참조를 제거한 뒤에 출력이 수행되게 됩니다.

하지만, 이 부분은 개별 구현에 따라 다르게 작성해도 무방합니다. 예를 들어, 말씀하신 대로 clear 메서드를 오버라이딩하여 바로 출력을 하거나, cleanUp 메서드를 호출하기 위해 별도로 메서드를 작성하여 호출하는 방법도 가능합니다.

단, PhantomReference 클래스를 상속 받으며 clear 메서드를 오버라이딩한 이유는, PhantomReference의 참조가 제거될 때 어떤 작업을 수행하고자 하는 경우에 오버라이딩하여 구현할 수 있기 때문입니다.

감사합니다.

정권호님의 프로필 이미지
정권호

작성한 질문수

질문하기