Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Casting to Generic with Interface Pointers

In the following sample code two classes EventA and EventB both implement the interface Historical. Java can automatically cast an EventA or EventB to Historical when one of these objects is passed as a parameter, as in the examineEvent method below. However, Java is no longer able to cast when a generic is introduced ie. from List<EventA> to List<Historical> -- Unless the target function (in this case findClosestValidEventIndex) is declared using List<? extends Historical>.

Can someone explain why this must be? It seems to me that the very use of an interface in a generic should automatically imply the <? 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);
   }
}
like image 711
Toaster Avatar asked Aug 14 '26 12:08

Toaster


1 Answers

Because List<EventA> is not List<Historical>. Imagine:

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
   ...
}

List<? extends Historical> means "a list of a one specific subtype of Historical", and you cannot add anything to it, because at compile time you don't know what the type is.

like image 103
Bozho Avatar answered Aug 17 '26 01:08

Bozho



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!