列表中的Java泛型实例-泛型可观察和所有

列表中的Java泛型实例-泛型可观察和所有,java,generics,Java,Generics,如何在Java中正确地建模一个列表,该列表包含一个泛型类型的多个实例,每个实例不一定具有完全相同的具体类型参数(而是一个共享的公共根类型) 考虑以下M(N)WE(最小(非)工作示例): 公共接口事件{ } 公共接口侦听器{ 无效句柄(T事件); } 公共类出版商{ 私有列表参数化发布者类。如果希望它是类型安全的,侦听器列表需要了解T public class Publisher<T extends Event> { private List<Listener<T

如何在Java中正确地建模一个列表,该列表包含一个泛型类型的多个实例,每个实例不一定具有完全相同的具体类型参数(而是一个共享的公共根类型)

考虑以下M(N)WE(最小(非)工作示例):


公共接口事件{
}
公共接口侦听器{
无效句柄(T事件);
}
公共类出版商{

私有列表参数化
发布者
类。如果希望它是类型安全的,
侦听器
列表需要了解
T

public class Publisher<T extends Event> {
    private List<Listener<T>> listeners = new ArrayList<>();

    public void addListener(final Listener<T> listener) {
        listeners.add(listener);
    }

    public void publish(final T event) {
        for (final Listener<T> listener : listeners) {
            try {
                listener.handle(event);
            } catch (final Exception ex) {
                // ...
            }
        }
    }
}
public class Publisher<T extends Event> {
    private List<Listener<? super T>> listeners = new ArrayList<>();

    public void addListener(final Listener<? super T> listener) {
        listeners.add(listener);
    }

    public void publish(final T event) {
        for (final Listener<? super T> listener : listeners) {
            try {
                listener.handle(event);
            } catch (final Exception ex) {
                // ...
            }
        }
    }
}

不,这对问题的用例不起作用。发布者本身不受任何特定
t
的约束。它应该能够处理任何类型的
事件
。它将容纳多个不同的侦听器(因此可能是一个
侦听器
和另一个
侦听器
)那么,你不打算把
EndEvent
传递给
监听器吗?你的发布者将把错误类型的事件传递给监听器。我相信编译器非常正确地识别了你的类设计中的类型安全问题。嗯,是的,这是一个非常有效的观点。我想我必须重新评估我的经验,然后通配符
表示一些未知但特定的类型。但是不能使用
句柄(事件)
,因为编译器不知道它是什么类型。要解决此问题,请根本不使用泛型;将所有
t
s替换为
event