Tuesday, December 21, 2010

Array Copy using Generics

If you look at the method definition of copy in the collections framework it looks something like this.

public static <T> void copy(List< ? super T > to, List <? extends T> from)

The ? in generics means wild card i.e. In this case any class or interface that is a super class of T for the first parameter or extends T as in the second parameter. An important concept that one should understand in this example is covariance. Arrays in java are covariance i.e. if Integer extends Number then Interger[] also extends Number[]. This is not the case when it comes to generic lists where List<Integer> is not a sub class of List<Number>. With this basic understanding lets simplify the above method definition and see what happens

public static <T> void copy(List<T> to, List <T> from)

Now let us call the method as follows.

List<Object> objs = Arrays.<Object>asList("San","John",1042);
List<Integer> ints = Arrays.<Integer>asList(10,20);
TestClass.<Object>copy(objs, ints); // Call(1)
TestClass.<Integer>copy(objs,ints); // Call (2)
TestClass.<Number>copy(objs,ints); // Call (3)

If the rule of covariance is applied then all three calls are not legal. as List<Integer> is not a subclass of List<Object> if you consider call (1) To make call (1) legal the declaration should be modified to

public static <T> void copy(List<T> to, List <? extends T> from)

With this method declaration call (1) is legal but how about (2) and (3) they are still not legal as List<Object> is not a subclass of List<Integer> for the "to" parameter same concept is applicable for call (3) and because of this we end up having public static <T> void copy(List< ? super T > to, List <? extends T> from) which is the most suitable for all calls. I would recommend reading the Java Generics and Collections by Maurice Naftalin to understand more about Generics in Java.

No comments: