【问题标题】:Java Generics compile errorJava泛型编译错误
【发布时间】:2012-05-16 16:59:25
【问题描述】:

我不明白为什么编译器不接受这段代码

import javax.swing.event.EventListenerList;

import java.util.EventListener;


public class GenericEventsManager {

   EventListenerList listeners = new EventListenerList();


   public <T extends EventListener> void addListener(T listener) {
      listeners.add(listener.getClass(), listener);
   }
}

我得到的错误是

The method add(Class<T>, T) in the type EventListenerList is not applicable for the arguments (Class<capture#1-of ? extends EventListener>, T)

addListener 中的参数是扩展 EventListener 的类型,所以 listener.getClass() 返回 Class&lt;? extends EventListener&gt;,这正是 EventListenerList.add 方法所期望的

有人能解释一下吗?我有一种感觉,它与 getClass() 在编译时没有被解析有关,但对我来说仍然没有意义

【问题讨论】:

    标签: java generics compiler-errors


    【解决方案1】:

    没有通配符的通用参数不是变体,因此需要完全相同的类型(不是子类型,不是超类型)。 (source)

    编译器根本不允许你这样做。正如错误消息所暗示的那样,Class 参数上的类型参数必须与第二个参数的类型完全相同相同,这在上面的代码中是不正确的。


    他们怎么可能不一样?

    因为listener.getClass()的返回类型是Class&lt;? extends EventListener&gt;,而不是Class&lt;T&gt;。你可以——但我确实不建议这样做——转换返回的Class 来编译:

    listeners.add((Class<T>)listener.getClass(), listener);
    

    这样做时您会收到编译器警告:

    Type safety: Unchecked cast from Class<capture#1-of ? extends EventListener> to Class<T>
    

    因为这不是(类型)安全强制转换。


    这可能(我真的不确定)的根本原因只是 EventListenerList#add() 声明中糟糕的 API 设计。通常PECS is used in this kind of situationadd() 没有通配符可能是有充分理由的。

    【讨论】:

    • 他们怎么可能不一样?
    • 我明白了。为什么编译器不能更进一步找出 T is "? extends EventListener"?
    • 因为Object#getClass() 不是这样声明的。请注意,您不能编写 Class&lt;T&gt; clazz = listener.getClass();Class&lt;EventListener&gt; clazz = listener.getClass();,因为它们也不会编译。
    【解决方案2】:

    是的,但在您的添加方法中,您指定的是 Class&lt;T&gt;,而不是 Class&lt;EventListener&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-17
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      相关资源
      最近更新 更多