Why do we need bounded wilcard <? extends T> in Collections.max() method

£可爱£侵袭症+ 提交于 2019-11-29 05:38:58

The difference is in the type returned, especially influenced by inference, whereby the type may be a type hierarchically between the Comparable type and the List type. Let me give an example:

class Top {
}
class Middle extends Top implements Comparable<Top> {
    @Override
    public int compareTo(Top o) {
        // 
    }
}
class Bottom extends Middle {
}

Using the signature you've provided:

public static <T extends Comparable<? super T>> T max(List<? extends T> list)

we can code this without errors, warnings or (importantly) casts:

List<Bottom> list;
Middle max = max(list); // T inferred to be Middle

And if you need a Middle result, without inference, you can explicitly type the call to Middle:

 Comparable<Top> max = MyClass.<Middle>max(list); // No cast

or to pass to a method that accepts Middle (where inference won't work)

someGenericMethodThatExpectsGenericBoundedToMiddle(MyClass.<Middle>max(list));

I don't know if this helps, but to illustrate the types the compiler as allowed/inferred, the signature would look like this (not that this compiles, of course):

public static <Middle extends Comparable<Top>> Middle max(List<Bottom> list)

The difference between

T max(Collection<? extends T> coll)

and

T wrongMax(Collection<T> xs)

is that the return type of the second version is exactly the same as the collection's element type T, while in the first version T can be a super type of the element type.

The second question: the reason for T extends Object makes sure that T is a class and not an interface.


Update: A slightly more "natural" demonstration of the difference: Suppose you define these two methods:

static void happy(ColoredPoint p, Point q) {}
static void happy(Point p, ColoredPoint q) {}

And call the first one them like this:

happy(coloredPoint, min(points));
happy(coloredPoint, wrongMin(points));

The type inference engine could be able to deduce that in the first call the return type of min should be Point and the code would compile. The second call would fail to compile since the call to happy is ambiguous.

Unfortunately the type inference engine isn't powerful enough at least in Java 7, so in reality both calls fail to compile. The difference is that the first call can be fixed by specifying the type parameter as in Algorithms.<Point>min, while fixing the second call would require an explicit cast.

Not an easy one, but i'll try to be as specific as possible:

in T max(Collection<? extends T> coll) you could pass an argument like this List<Animal> or List<Cat> or List<Dog>, and in T wrongMax(Collection<T> xs) where T is Animal you can't pass as an Argument this List<Dog>, List<Cat> of course in Runtime you could add Cat or Dog objects in List<Animal> but in compilation time you wouldn't be able to pass a subclass of Animal in the Type of the List being passed as an argument in the wrongMax method, in the other hand, in the max method you could. Sorry for my english, i still learning it :), Regards.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!