有界通配符和函数参数的关系

Relation of bounded wildcard and function argument

假设我们 SubSuper 继承 compareTo:

class Super implements Comparable<Super> {
    @Override public int compareTo(Super o) {
        return 0;
    }
}

class Sub extends Super {}

以及采用 Comparable 列表的通用方法 max:

public static <T extends Comparable<T>> T max(List<T> list) {
    return null;
}

如果我们尝试用 Sub 的列表调用 max,我们将得到一个编译时错误,因为 Sub 没有实现 Comparable<Sub>。这就是我所期望的!

max(new ArrayList<Sub>()); // error, Sub should implement Comparable<Sub>

然后我更改 max 参数以仅接受 T 的两个实例并对其进行测试:

public static <T extends Comparable<T>> T max(T t, T t2) {
    return null;
} 
max(new Sub(), new Sub());

没有编译时错误,非运行时!

max 方法在类型安全方面有何区别?

max(T,T) 让编译器推断 T 可以是 Super 并对参数进行扩大转换。

另一方面,max(List<T>) 不是那么灵活,因为泛型是不变的(在 Paul 的 link 中有解释)。编译器无法对 List 执行转换,因此 T 必须正好是 Sub.

在这两种情况下,您都应该更改绑定到此的类型变量:

public static <T extends Comparable<? super T>> T max(List<T> list) {...}
//                                  ^^^^^^^^^

它的限制较少,可以让您这样做,例如:

Sub s0 = max(new ArrayList<Sub>());
Sub s1 = max(new Sub(), new Sub());

第 2 行也不会使用更严格的界限进行编译,您可能错过了,因为您在示例中忽略了 return 值。

? super T也是how Java SE does it。)