Reputation: 56
I am confusing about the subtype of generic in java. I have a sample below.
public class Class2{
public static <T extends Number> void set(List<T> list){
List<T> numberList = list;;
}
public static <T extends Integer> List<T> get(){
List<T> list = new ArrayList<T>();
return list;
}
}
//Does this line is the same as the two below line?
Class2.set(Class2.get());
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numberList = intList;
My question: what is different between
Class2.set(Class2.get());
and
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numberList = intList;
UPDATE #1: change
public static <T> void set(List<T> list)
to
public static <T extends Number> void set(List<T> list)
UPDATE #2: Look at the image (took from docs.oracle about generic in java) Link:https://docs.oracle.com/javase/tutorial/figures/java/generics-wildcardSubtyping.gif
From the image we know that List<? extends Integer>
is subtype of List<? extends Number>
. And we can assign a variable of List<? extends Integer>
for a variable of List<? extends Number>
.
In my example above, do I really assign a variable of List<T extends Integer>
for a variable of List<T extends Number>
? If so, is List<T extends Number>
is subtype of List<T extends Integer>
? Can you guy so me how to prove that if it is or not?
P/S: Link post of oracle docs : https://docs.oracle.com/javase/tutorial/java/generics/subtyping.html
Upvotes: 2
Views: 4747
Reputation: 24157
The method set in class2
takes a list where all elements are of type T
and T
is Number
or any sub class of Number
:
public static <T extends Number> void set(List<T> list){
List<T> numberList = list;
}
This will assign the input parameter list
to numberList
and both can contain element of only one type which is represented by T
(T
needs to be Number
or subtype of Number
e.g. Integer
).
On the other hand method get
will return a list of element where each element is of type T
and <T extends Integer>
means T
has to be Integer
or one of the subclass of Integer
. We need to understand that this T
is not same as the one defined in method set
above.
Now the following line:
Class2.set(Class2.get());
actually initializes numberList
with elements where each element is of same type T
. On the other hand we have:
List<? extends Integer> intList = new ArrayList<>();
The confusion seems to narrow down between: List <? extends Integer>
and List <T extends Number>
. So the difference IMO is:
List <? extends Integer>
means it is a list of "unknown type" which will extend Integer
and as per the rule PECS(Producer Extends Consumer Super) this can produce elements but can not consume elements.List<T extends Integer>
is a list of type with super class Integer
and we can read or add the elements into the list.
On a side note the signature should have been List <? extends Number>
and not List <? extends Integer>
as Integer
is final
and cannot be sub-classed.
Using extends
List<? extends Number> list1 = new ArrayList<Number>(); // Number "extends" Number (in context)
List<? extends Number> list2 = new ArrayList<Integer>(); // Integer extends Number
List<? extends Number> list3 = new ArrayList<Double>(); // Double extends Number
Using super
List<? super Integer> list4 = new ArrayList<Integer>(); // Integer is a "superclass" of Integer
List<? super Integer> list5 = new ArrayList<Number>(); // Number is a superclass of Integer
List<? super Integer> list6 = new ArrayList<Object>(); // Object is a superclass of Integer
EDIT:
The method get
returns a list of elements with type T
(T can be Integer
or subtype):
List<Integer> list1 = Class2.get();
Now for the set
method all the following will work:
List<Integer> list1 = Class2.get();
Class2.set(list1);
List<Number> list2 = new ArrayList<Number>();
Class2.set(list2);
List<Integer> list3 = new ArrayList<Integer>();
Class2.set(list3);
As mentioned in doc
Integer
is a subtype ofNumber
butList<Integer>
is not subtype ofList<number>
, rather these are not related at all. The common parent ofList<Number>
andList<Integer>
isList<?>
.
As I explained above List<? extends Integer>
will accept Integer
and List<?extends Number>
is even more relaxing. The relation between all these is expressed by the image.
Upvotes: 1