6

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.

Dipesh Gupta
  • 787
  • 1
  • 7
  • 20
  • why does it matter what exactly T is? Generics are only used for type checking at compile-time, so the compiler should only care that there exists *some* T that works; beyond that it makes no difference – newacct Mar 23 '12 at 18:37

3 Answers3

4

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));
  }

}
UmNyobe
  • 22,539
  • 9
  • 61
  • 90
benmmurphy
  • 2,503
  • 1
  • 20
  • 30
  • But this is different. You are forcing copy to return String[] so forcing T to be String... This is not related. – UmNyobe Mar 23 '12 at 12:55
  • i'm not forcing T to be string. the compiler is actually complaining that it is not String. i just added the return type and the deliberate type error to trick the compiler into revealing what it thinks the type of T is. "found : java.lang.Integer[]" .. i should have removed the array type from the return type but there it is. – benmmurphy Mar 23 '12 at 14:46
  • But i still not get it, how is it decided? Can you explain the flow of decision, how is it chosing amongst the the three options- Comparable, Serializable, Number and Ineger? – Dipesh Gupta Mar 24 '12 at 15:50
  • sorry the option stands to four, as every class is a subclass of itself. – Dipesh Gupta Mar 24 '12 at 16:07
  • in the JLS it says to choose the most specific type that satisfies the constraints. and Integer < Number & Serializable & Comparable so Integer is the most specific type. – benmmurphy Mar 24 '12 at 23:11
2

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

Andrejs
  • 26,885
  • 12
  • 107
  • 96
  • But here in my function, the datatype of T is Number. I want to know how. If declared explicitly, as you have done, it can be Serializable or Comparable..that part I know. – Dipesh Gupta Mar 24 '12 at 16:13
  • What makes you think its Number? It can be any of those types but Number is a better example so I think thats why its mentioned in the book. – Andrejs Mar 24 '12 at 16:20
  • You may be correct, the language says "the T is taken to be number". so the language is not mentioning that T is actually number. May be it is the case. But still the question remains as it is. What is the datatype of T call the function as mentioned in my question, without explicitly mentioning the parameters? – Dipesh Gupta Mar 24 '12 at 17:25
  • If you hover over copy() method in Eclipse it will tell you its Integer ;) – Andrejs Mar 25 '12 at 13:11
  • You are correct and well thanks for the explanations. I realized one golden rule that, in case of gnerics Java does not allow to add any object of whose datatype JVM does not know. So in my case of example: For dst (Object super T) and src (Integer extends T), out of the four choices Comparable, Serializable, Number and Integer, JVM picks Integer as Integer is the closest to intersection results. – Dipesh Gupta Mar 30 '12 at 11:41
-1

Object class is the super type of Serializable and Comparable also
This is not true, Serializable and Comparable are interfaces and have no relation with Object.

Additionally the super ? is the exact inverse of extends ? which means it cannot be applied to interfaces. it can be applied to interfaces.

When you write ? extends T it means ? is an unknown subtype of T, probably T itself. I believe the JVM resolve T bottom up which means T is in fact Integer not Number(correct me if I am wrong).

Then

   Collections.copy(objs, ints)

is in fact

   Collections.<Integer>(objs, ints)
UmNyobe
  • 22,539
  • 9
  • 61
  • 90
  • if you change the return type from void to T then it resolves T as Integer. – benmmurphy Mar 23 '12 at 11:33
  • I don't understand. Can you explain please? – UmNyobe Mar 23 '12 at 11:45
  • i've added an answer which shows changing the return type and I added a compile error to force the compiler to barf what the return type is. – benmmurphy Mar 23 '12 at 11:58
  • all interfaces are subtypes of `Object` – newacct Mar 23 '12 at 18:33
  • http://stackoverflow.com/questions/4269235/is-collection-a-subtype-of-object-in-java Hi UmNyobe, I have added a link. Have a look at it. It explains that interfaces are subtypes of Object according to JLS. – Dipesh Gupta Mar 24 '12 at 16:10
  • @DipeshGupta Are you sure? The top answer seems to argue that interfaces inherit only from other interfaces. – UmNyobe Mar 24 '12 at 22:55
  • @UmNyobe: see JLS 4.10.2 "the direct supertypes of C are ... The type Object, if C is an interface type with no direct superinterfaces." – newacct Mar 25 '12 at 19:30