Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is the datatype of type parameter decided in covariance and contravariance?

I was reading the book Java Generics and Collections By Maurice Naftalin, Philip Wadler, and within the first two chapters I ended up in having my head messed up with doubts. I was not able to figure out the answers.

In the call:

 public static <T> void copy(List<? super T> dst, List<? extends T> src) {
 for (int i = 0; i < src.size(); i++) {
 dst.set(i, src.get(i));
 }
}


 List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
 List<Integer> ints = Arrays.asList(5, 6);
 Collections.copy(objs, ints);
 assert objs.toString().equals("[5, 6, four]");

During call to the function 'copy':
1st parameter: ?= Object
2nd Parameter: ?=Integer

But what is the datatype of T? How is it decided by jvm based on the erasure implementation?

It is said in the book that: In the line Collections.copy(obj,ints), the type parameter T is taken to be Number. The call is permitted because objs has type List<Object>, which is a subtype of List<? super Number> (since Object is a supertype of Number, as required by the super) and ints has type List<Integer>, which is a subtype of List<? extends Number> (since Integer is a subtype of Number, as required by the extends wildcard).

But as Integer implements Serializable and Comparable both, aprt from extending Number class and Object class is the super type of Serializable and Comparable also.

So why not that T is taken as Serializable or Comparable instead of Number, because the Substitution Principle will allow it to be taken.

Thanks in advance.

like image 615
Dipesh Gupta Avatar asked Mar 23 '12 08:03

Dipesh Gupta


2 Answers

http://docs.oracle.com/javase/specs/jls/se7/jls7.pdf

From the 'simple' example the JLS says it chooses the most specific type that satisfies all the constraints it generates.

15.12.2.7 Inferring Type Arguments Based on Actual Arguments

A supertype constraint T :> X implies that the solution is one of supertypes of X. Given several such constraints on T, we can intersect the sets of supertypes implied by each of the constraints, since the type parameter must be a member of all of them. We can then choose the most specific type that is in the intersection

Copy.java:11: incompatible types
found   : java.lang.Integer[]
required: java.lang.String[]
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6));
                       ^
1 error
➜  /tmp  cat Copy.java 
import java.util.*;
public class Copy {
public static <T> T[] copy(List<? super T> dst, List<? extends T> src) {
   for (int i = 0; i < src.size(); i++) {
      dst.set(i, src.get(i));
   }

   return null;
  }
  public static void main(String[] args) {
    String[] res = copy(Arrays.<Object>asList(2, 3.14, "four"), Arrays.asList(5, 6));
  }

}
like image 127
benmmurphy Avatar answered Nov 12 '22 20:11

benmmurphy


T is decided based upon the arguments but can be specified explicitly as well. So, yes it can be Comparable and Serializable.

All of these are valid:

     Collections.<Number>copy(objs, ints);
     Collections.<Comparable>copy(objs, ints);
     Collections.<Serializable>copy(objs, ints);
     Collections.<Integer>copy(objs, ints);

     Collections.copy(objs, ints); // implicitly Integer

When no type is specified Integer is picked due to the way <? extends Integer> is handled and explained in java documentation

like image 43
Andrejs Avatar answered Nov 12 '22 19:11

Andrejs