我已经实施了抽象通用提供商,以通知一堆通用听众 E, ,后代必须覆盖 notifyListener(E) 带有特定的通知代码。对于听众的支持列表,我选择 WeakHashMap<K,V>. 。听众必须被视为弱参考:

abstract public class NotificationProvider<E> {

    private Map<E, Object> listeners = new WeakHashMap<E, Object>();

    public addListener(E listener) {
        listeners.put(listener, null);
    }

    public void notifyListeners() {
        for (E listener: listeners.keySet())
            notifyListener(listener);
    }

    abstract protected void notifyListener(E listener);
}

典型用途:

    NotificationProvider<MyListener> provider;
    provider = new NotificationProvider<MyListener>() {
        @Override
        protected void notifyListener(MyListener listener) {
            listener.myNotification();
        }
    }
    provider.addListener(myListener1);
    provider.addListener(myListener2);
    provider.notifyListeners();

一切都很好,但是当我需要时 AbstractList 后裔班级作为听众,支持 WeakHashMap 仅接受一个侦听器实例!很明显 - 方法 hashCode()equals() 在听众返回所有实例(空列表)的相同值,所以 WeakHashMap.put 仅替换先前添加的侦听器。

    public class MyList extends AbstractList<MyItem> {
        // some implementation
    }
    NotificationProvider<MyList> provider;
    provider = new NotificationProvider<MyList>() {
        @Override
        protected void notifyListener(MyList listener) {
            // some implementation
        }
    }
    MyList list1 = new MyList();
    MyList list2 = new MyList();
    provider.addListener(list1);
    provider.addListener(list2); 
    provider.notifyListeners();  // only list2 instance is notified

最好的解决方案是什么?

  1. 使用另一个非施加码备用集合 - 但是 WeakHashMap 对我来说真是太好了,因为自动为我管理弱参考

  2. 使用非生成侦听器,例如简单的抽象类 equals() { return (this == object); } 实施 - 但这不是那么灵活

  3. 将一些包装器用于具有简单equals()的听众 - 但此包装器不能透明 addListener(E) 呼叫者由于参考薄弱

另一个想法?

有帮助吗?

解决方案

WeakHashMap 有点破碎。它使用弱键,但不使用身份散列。除非 equals()hashCode() 您的关键类型使用“身份”,您不应使用 WeakHashMap. 。相反,您需要的东西是 WeakHashMapIdentityHashMap.

一种可能性是使用 MAPMAKER 来自Google收藏。如果密钥弱或软键,它将自动使用键的身份哈希/平等。例如:

ConcurrentMap<K, V> myMap = new MapMaker().weakKeys().makeMap();

其他提示

问题的症结似乎是您的侦听器实施是在子类别 AbstractList, ,但不屈服 equals() / hashCode(). 。我强烈建议您反对这种遗传(实施继承),因为它违反了OO-PRINCIPLE(多态性替代性原则)。

实施一个可能引用的自定义侦听器类要好得多 AbstractList 如果需要一个,那也提供了自己的 equals()hashCode() 实施。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top