私はこの質問の変種を見たことがあると思いますが、「決定的な回答」はありません。以下のコードでは、SomeEventManagerがsomeImplClassTwo.myEventListenerAおよびsomeImplClassTwo.myEventListenerBへの参照を保持し、someImplClassTwoがガベージコレクションされないようにして、someEventManager.notifyListeners()が2回目に出力されることを理解しています。呼び出される。リスナーをJavaで自動的に登録解除する「クリーン」な方法はありますか?
しかし、SomeImplClassのユーザーは、実装に関与するリスナーがあることを知らなくてもいいし、これらのリスナーは手動で未登録(つまりSomeImplClass.releaseListeners())する必要があります。 SomeImplClassオブジェクトを解放します。
これを行うにはクリーンな/受け入れられた方法がありますか?
p.s.私は既にfun()のためにfinalize()を行っていますが、SomeImplClassのどちらのインスタンスに対してもGCがこの場合でも試行されていないことを確認しました。だから、それは潜在的な解決策としての非スターターではないようです。
テストドライバ
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) –