简体   繁体   中英

Relation of bounded wildcard and function argument

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM