Suppose we have Sub
inherit compareTo
from Super
:
class Super implements Comparable<Super> {
@Override public int compareTo(Super o) {
return 0;
}
}
class Sub extends Super {}
And generic method max
that takes a list of Comparable
:
public static <T extends Comparable<T>> T max(List<T> list) {
return null;
}
If we try to call max
with the list of Sub
's we will get a compile-time error because Sub
doesn't implement Comparable<Sub>
. This is what I expected!
max(new ArrayList<Sub>()); // error, Sub should implement Comparable<Sub>
Then I change max
arguments to accept just two instances of T and test it:
public static <T extends Comparable<T>> T max(T t, T t2) {
return null;
}
max(new Sub(), new Sub());
No compile-time error, non runtime!
What is the difference between max
methods in terms of type safety?
max(T,T)
lets the compiler infer that T
can be Super
and do a widening conversion on the arguments.
On the other hand, max(List<T>)
is not so flexible, because generics are invariant (explained in Paul's link). The compiler can't perform a conversion on the List
, so T
has to be exactly Sub
.
In both cases, you should change the type variable bound to this:
public static <T extends Comparable<? super T>> T max(List<T> list) {...}
// ^^^^^^^^^
It's less restrictive and will let you do eg:
Sub s0 = max(new ArrayList<Sub>());
Sub s1 = max(new Sub(), new Sub());
Line 2 also wouldn't compile with the more restrictive bound, which you may have missed because you ignore the return value in your example.
(The ? super T
is also how Java SE does it .)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.