我编写了一个实现Comparable接口的类Fruit和2个子类:Apple和Orange。 我写了一个方法,它返回2个水果之间的最大值(无论它意味着什么)。
请注意,我没有使用任何带有super的通配符。
我认为max方法会失败,因为Comparable接口不是由Apple或Orange直接实现的。
问题: 为什么建议使用这种形式的通配符:
<T extends Comparable<? super T>>
如果它也没有超级工作吗?
以下是代码:
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);
}
}
答案 0 :(得分:2)
在您的情况下,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
可以与Apple
进行比较等等。
如果您将其更改为:
public static <T extends Comparable<? super T>> T getMax(List<T> xs) {
//...
}
然后它适用于List<Apple>
和List<Orange>
。
答案 1 :(得分:0)
当Fruit实现Comparable
和Apple
以及Orange
扩展Fruit时,他们只是从compareTo
继承Fruit
实现。
如果您愿意,可以覆盖Apple
和Orange
子类中的compareTo方法。
我认为这是你对继承的理解,而不是你对>
符号的理解。
<T extends Comparable<? super T>>
您在此定义类型T
扩展了Comparable,因此您可以安全地在对象上调用compareTo
方法。
传递给方法DO的两个对象都具有可比性(因为它们扩展了Fruit,它实现了Comparable)