如何声明泛型处理程序的泛型multitype集合

Ant*_*sss 7 java generics

我总是很难将泛型与集合和通配符一起使用.

所以这是以下地图.我想保留特定类型的数据包类的处理程序集合.

private ConcurrentHashMap<Class<? extends Packet>, List<PacketListener<? extends Packet>>> listeners = new ConcurrentHashMap<>();
Run Code Online (Sandbox Code Playgroud)

而且 PacketListener

public interface PacketListener<T extends Packet> {

    public void onOutgoingPacket(Streamer streamer, T packet);

    public void onIncomingPacket(Streamer streamer, T packet);
}
Run Code Online (Sandbox Code Playgroud)

现在我想做的是根据传入的数据包类获取侦听器,如下所示:

public <T extends Packet> void addPacketListener(Class<T> clazz, PacketListener<T> listener) {
    if (listeners.containsKey(clazz) == false) {
        listeners.putIfAbsent(clazz, new LinkedList<PacketListener<T>>());  // ERROR
    }
    List<PacketListener<? extends Packet>> list = listeners.get(clazz);
    list.add(listener);
}

public <T extends Packet> List<PacketListener<T>> getPacketListeners(Class<T> clazz) {
    List<PacketListener<T>> list = listeners.get(clazz);// ERROR
    if (list == null || list.isEmpty()) {
        return null;
    } else {
        return new ArrayList<>(list);
    }
}
Run Code Online (Sandbox Code Playgroud)

最后我想执行这样的调用

private <T extends Packet> void notifyListeners(T packet) {
    List<PacketListener<T>> listeners = streamer.getPacketListeners(packet.getClass());
    if (listeners != null) {
        for (PacketListener<? extends Packet> packetListener : listeners) {
            packetListener.onIncomingPacket(streamer, packet);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我所得到的只是很多错误.是因为收集声明中的通配符吗?有可能实现这样的解决方案吗?

Ada*_*old 5

有一个很好的形象: 佩奇 在其中一个可以解释你这个问题的答案中.

这个东西叫PECS,代表

制片extends人和消费者super.

TL; DR:你只能二者addget从/到一个集合与具体类型(T).您可以得到任何T与(和其可能的亚型)T extends Something,你可以添加任何Something一个CollectionT super Something,但你不能是双向的:因此你的错误.