我编写了一个 Fruit 类,它实现了 Comparable 接口(interface)和 2 个子类:Apple 和 Orange。 我编写了一个方法,它返回 2 个水果之间的最大值(无论它意味着什么)。
请注意,我没有在 super 中使用任何通配符。
我认为 max 方法会失败,因为 Comparable 接口(interface)不是由 Apple 或 Orange 直接实现的。
问题: 为什么建议使用这种形式的通配符:
<T extends Comparable<? super T>>
如果没有 super 也能工作吗?
这是代码:
package main;
//Note that I did not use the super wildcard: <T extends Comparable<? super T>>
class Max {
public static <T extends Comparable<T>> T getMax(T x, T y) {
return x.compareTo(y) >= 0 ? x : y;
}
}
class Fruit implements Comparable<Fruit> {
public String name;
public Fruit(String name) {
this.name = name;
}
@Override
public int compareTo(Fruit other) {
return name.compareTo(other.name) == 0 ? 0 :
name.compareTo(other.name) > 0 ? 1 : -1;
}
}
class Apple extends Fruit {
String name;
public Apple(String name) {
super(name);
}
}
class Orange extends Fruit {
String name;
public Orange(String name) {
super(name);
}
}
public class Main {
public static void main(String[] args) {
Apple a = new Apple("apple");
Orange o = new Orange("orange");
Fruit f = Max.getMax(a, o); //It should not be allowed because T does not implement Comparable directly
System.out.println(f.name);
}
}
最佳答案
就您而言,T
可以选择为Fruit
,以及声明 Fruit f = Max.getMax(a, o);
会正确进行类型检查。因此,它有效。
Max.getMax()
具有参数类型 T
,以及 T
子类型的实例也是 T
的实例,因此该方法接受 T
的任何子类型作为参数。
但是请注意,您的方法仍然存在 T
的问题只能推断为Fruit
,而不是Apple
,因此您无法返回 Apple
:
Apple a = Max.getMax(apple1, apple2);
但是,请考虑 T
是泛型类型参数:
public static <T extends Comparable<T>> T getMax(List<T> xs) {
//...
}
泛型不是协变的,所以这个方法只能接受List<Fruit>
,但不是List<Apple>
或List<Orange>
,尽管 Apple
s 可以与 Apple
进行比较等
如果将其更改为:
public static <T extends Comparable<? super T>> T getMax(List<T> xs) {
//...
}
那么它就可以工作 List<Apple>
和List<Orange>
.
关于Java通配符具有 super 意外的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24629547/