Java:使用接口指针转换为通用

Toa*_*ter 2 java generics casting

在下面的示例代码的两个班EventA,并EventB都实现了interface Historical.Java可以自动转换一个EventAEventBHistorical当这些对象中的一个作为参数被传递,如在examineEvent下面的方法.但是,当引入泛型时,Java不再能够进行转换,即.from List<EventA>to List<Historical>- 除非findClosestValidEventIndex使用声明目标函数(在本例中)List<? extends Historical>.

有人可以解释为什么一定是这样吗?在我看来,泛型中接口的使用应该自动暗示<? extends Interface>.

public class SampleApplication {

   public interface Historical {
      public DateTime getDate();
   }   

   public static class EventA implements Historical {
      private DateTime date;
      @Override
      public DateTime getDate() {
         return date;
      }
   }

   public static class EventB implements Historical {
      private DateTime date;
      @Override
      public DateTime getDate() {
         return date;
      }
   } 

   private static int findClosestValidEventIndex(List<Historical> history, DateTime when) {
      // do some processing
      return i;
   }

   private static int examineEvent(Historical event){
      return j;
   }

   public static void main(String[] args) {
      DateTime target = new DateTime();
      // AOK
      EventA a = new EventA(target);
      int idy = examineEvent(a);
      // Type Error --- Unless 
      List<EventA> alist = new ArrayList<EventA>();
      int idx = findClosestValidEventIndex(alist, target);
   }
}
Run Code Online (Sandbox Code Playgroud)

Boz*_*zho 6

因为List<EventA>不是 List<Historical>.想像:

List<EventA> list = ...;
List<Historical> h = (List<Historical>) list;
h.add(new EventB()); //type-safety of list is compromised
for (EventA evt : list) { // ClassCastException - there's an EventB in the lsit
   ...
}
Run Code Online (Sandbox Code Playgroud)

List<? extends Historical> 表示"历史的一个特定子类型的列表",并且您不能向其添加任何内容,因为在编译时您不知道该类型是什么.