2014-07-08 90 views
1

我写了一个实现了Comparable接口和2个子类的类Fruit:Apple和Orange。 我写了一个方法,返回2个水果之间的最大值(不管它是什么意思)。带有超级意外行为的Java通配符

请注意,我没有使用超级通配符。

我认为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

唯一令人担忧的是子类中外部的'name'字段,它们保持为空,并隐藏'Fruit.name'。您应该使字段最终在'受保护的最终字符串名称;'在水果中,因此它不能被更改,并且可比较合同保持正常。 –

+0

[什么是语法?](http://stackoverflow.com/questions/2827585/what-is-super-t-syntax) –

回答

0

水果实现ComparableAppleOrange延长水果那么他们只需从Fruit继承compareTo实施。

如果您愿意,您可以覆盖AppleOrange子类中的compareTo方法。

我认为这是您对继承的理解,而不是您对>符号的理解。

<T extends Comparable<? super T>>

这里你定义的类型T延伸可比,所以你可以安全地调用对象的方法compareTo

你都传递给方法的对象不会延长可比性(因为他们延长果实,实现可比)

+0

对不起,也许我的问题不清楚。为什么这个通配符总是建议>?如果它仍然有效? – Kami

+0

这只是告诉编译器只允许扩展COMPrable接口的对象被传入该方法。没有它,你不能调用compareTo方法,因为你不知道参数是否实现了它。但是你的所有对象都会实现它。 – cowls

+0

所以,我对前一个问题的接受答案是错误的?这里是链接:https://stackoverflow.com/questions/24609278/java-wildcards-with-super – Kami

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>