简体   繁体   English

Java Generics编译错误

[英]Java Generics compile error

I don't understand why the compiler doesn't accept this code 我不明白为什么编译器不接受这个代码

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 error I get is 我得到的错误是

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

The argument in addListener is of a type that extends EventListener, so listener.getClass() returns Class<? extends EventListener> addListener中的参数是一个扩展EventListener的类型,所以listener.getClass()返回Class<? extends EventListener> Class<? extends EventListener> , which is exactly what the EventListenerList.add method expects Class<? extends EventListener> ,这正是EventListenerList.add方法所期望的

Can someone explain this? 有人可以解释一下吗? I have a feeling that it has something to do with getClass() not being resolved at compile time but it still doesn't make sense to me 我有一种感觉,它与getClass()有关,在编译时没有得到解决,但它对我来说仍然没有意义

Generic parameters without wildcards are not variant and therefore require exactly the same types (not sub-types, not super types). 没有通配符的通用参数不是变体,因此需要完全相同的类型(不是子类型,不是超类型)。 ( source ) 来源

The compiler simply will not let you do this. 编译器根本不会让你这样做。 As the error message implies, the type parameter on the Class parameter must be exactly the same as the type of the second argument, which is not true in the code above. 正如错误消息所暗示的, Class参数上的type参数必须与第二个参数的类型完全相同 ,在上面的代码中不是这样。


How can they not be identical? 他们怎么可能不一样?

Because the return type of listener.getClass() is Class<? extends EventListener> 因为listener.getClass()的返回类型是Class<? extends EventListener> Class<? extends EventListener> , not Class<T> . Class<? extends EventListener> ,而不是Class<T> You could — but I do not recommend doing so — cast the returned Class to make this compile: 你可以 - 但我不建议这样做 - 转换返回的Class来进行编译:

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

You'll get a compiler warning when doing so: 这样做时会收到编译器警告:

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

because this is not a (type)safe cast. 因为这不是(类型)安全演员。


The root cause of this might (I'm honestly not sure) be simply poor API design in the declaration of EventListenerList#add() . 这可能的根本原因(我老实说不确定)只是在EventListenerList#add()的声明中简单的API设计。 Typically PECS is used in this kind of situation ; 通常PECS用于这种情况 ; it's possible there's a good reason that add() is not wildcarded. 可能有一个很好的理由, add()不是通配符。

是的,但在您的add方法中,您指定的是Class<T> ,而不是Class<EventListener>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM