我相信我已經看到這個問題的變種,但沒有「確定的答案」。在下面的代碼中,我明白SomeEventManager持有對someImplClassTwo.myEventListenerA和someImplClassTwo.myEventListenerB的引用,並且這不允許someImplClassTwo被垃圾收集,並且這導致第二次生成的輸出someEventManager.notifyListeners()是調用。但是,我真的希望SomeImplClass的用戶不必知道在實現中有涉及的監聽器,並且這些監聽器需要手動取消註冊(即SomeImplClass.releaseListeners())釋放SomeImplClass對象。有沒有一種「乾淨」的方式來自動取消在Java中註冊監聽器?
是否有乾淨/可接受的方式來做到這一點?
p.s.我已經玩過finalize(),只是爲了好玩,並且確認GC在這種情況下甚至沒有嘗試過,對於任何一個SomeImplClass的實例。所以,這似乎是一個不可能的解決方案。
測試驅動
public class TestDriver {
public static void main(String[] args) {
SomeEventManager someEventManager = SomeEventManager.getInstance();
SomeImplClass someImplClassOne = new SomeImplClass("One");
SomeImplClass someImplClassTwo = new SomeImplClass("Two");
someEventManager.notifyListeners();
someImplClassOne.releaseListeners();
someImplClassOne = null;
someImplClassTwo = null;
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
}
someEventManager.notifyListeners();
}
}
事件接口
public interface SomeEventListener {
public void handleSomeEvent();
}
事件管理器
import java.util.ArrayList;
import java.util.List;
public class SomeEventManager {
private static SomeEventManager eventManager = null;
private List<SomeEventListener> listeners = null;
private SomeEventManager() {
listeners = new ArrayList<SomeEventListener>();
}
public static SomeEventManager getInstance() {
if (eventManager == null) {
eventManager = new SomeEventManager();
}
return eventManager;
}
public void addListener(SomeEventListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
public void removeListener(SomeEventListener listener) {
listeners.remove(listener);
}
public void notifyListeners() {
for(SomeEventListener listener : listeners) {
listener.handleSomeEvent();
}
}
}
事件監聽器實現
public class SomeImplClass {
private InnerEventListener myEventListenerA = null;
private InnerEventListener myEventListenerB = null;
private String id = null;
public SomeImplClass(String id) {
this.id = id;
myEventListenerA = new InnerEventListener(id + "_A");
myEventListenerB = new InnerEventListener(id + "_B");
}
public void releaseListeners() {
myEventListenerA.unregisterListener();
myEventListenerB.unregisterListener();
}
private class InnerEventListener implements SomeEventListener {
private SomeEventManager someEventManager = null;
private String id = null;
public InnerEventListener(String id) {
someEventManager = SomeEventManager.getInstance();
this.id = id;
registerListener();
}
public void registerListener() {
someEventManager.addListener(this);
}
public void unregisterListener() {
someEventManager.removeListener(this);
}
public void handleSomeEvent() {
System.out.println("InnerEventListener->" + id);
}
}
}
請參閱['WeakHashMap'](http://stackoverflow.com/questions/5511279/what-is-a-weakhashmap-and-when-to-use-it) –