问题<t extends =“”可比较<?=“”super =“”t =“”>&gt; </t>

时间:2011-07-15 07:53:59

标签: java generics collections

我有三个类:1.class Algorithm max()Collection中找到最大值:

public class Algorithm {

    public static <T extends Comparable<T>> T max(Collection<? extends T> coll) {
        T max = coll.iterator().next();

        for (T elm : coll) {
            if (max.compareTo(elm) < 0)
                max = elm;
        }

        return max;
    }
}

2.Class Fruit

public class Fruit implements Comparable<Fruit> {
    private String name;
    private int size;

    public Fruit(String name, int size) {
        this.name = name;
        this.size = size;
    }

    public int compareTo(Fruit that) {
        if (size < that.size)
            return -1;
        else if (size == that.size)
            return 0;
        else
            return 1;
    }
}

3.class Apple延长Fruit

public class Apple extends Fruit {
    public Apple(int size) {
        super("Apple", size);
    }
}

现在的问题是:

public class Main
{
    public static void main(String[] args) {        
        Apple a1 = new Apple(10);
        Apple a2 = new Apple(34);

        List<Apple> apples = Arrays.<Apple>asList(a1, a2);

        System.out.println(Collections.max(apples).size);
    }
}

根据这篇文章Java - Syntax Question: What is 我应该这样写:public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll)。但它现在工作正常。为什么?类Apple未实现Comparable<Apple>,且没有super

[UPDATE]
Java Generics and Collections Book说:

  

没有super通配符,找到List<Apple>的最大值   即使找到List<Fruit>的最大值,也是非法的   允许的。

3 个答案:

答案 0 :(得分:5)

假设我们将max方法更改为:

<T extends Comparable<T>> T max(Collection<? extends T> coll)

由于max未实现List<Apple>,因此无法获得Apple的{​​{1}},它会实现Comparable<Apple>。但是你和我完全清楚Comparable<Fruit>知道如何将自己与另一个Apple进行比较,因为它继承了这个功能。

我们通过将Fruit的声明更改为此来解决问题:

max

这意味着我们接受任何类<T extends Comparable<? super T>> T max(Collection<? extends T> coll) ,以便:

  1. T或......
  2. 某些T implements Comparable<T>
  3. T implements Comparable<X>XX
  4. 的超类

    为了找到T,我们必须确保max的任何实例都可以安全地接受另一个T实例作为其T方法的参数。

    在第一个场景中,很明显compare的任何实例都可以安全地接受另一个T实例作为其T方法的参数。

    在第二种情况下,compare(T)的任何实例都可以安全地接受T的另一个实例作为其T方法的参数,因为compare(X)的所有实例也是实例T

    您的示例说明了第二种情况,X对应TApple对应X

答案 1 :(得分:1)

您使用Collections.max(apples)代替Algorithm.max

Collections.max声明略有不同:

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)

答案 2 :(得分:0)

很抱歉把它带回去,但我认为这很重要。从Collections.max()更改为Algorithm.max()时,您的代码是否已停止正常工作?我已经在jdk8中完成了一个类似的测试,我不明白它为什么工作正常,而根据Java Generics和Collections它不应该。

我有一个Fruit抽象类(实现Comparable):

public abstract class Fruit implements Comparable<Fruit> {
    private String name;
    private int size;

    public Fruit(String name, int size) {
        this.name = name;
        this.size = size;
    }

    public int compareTo(Fruit that) {
        if (size < that.size)
            return -1;
        else if (size == that.size)
            return 0;
        else
            return 1;
    }
}

然后我有一个Apple扩展Fruit类:

public class Apple extends Fruit {
    public Apple(String name, int size) {
        super(name, size);
    }
}

最后:

 public class GenericsTest {

    @Test
    public void test1() {
        final Apple a1 = new Apple("apple1", 50);
        final Apple a2 = new Apple("apple2", 70);
        final Apple a3 = new Apple("apple3", 34);

        final List<Apple> apples = Lists.newArrayList(a1, a2, a3);

        System.out.println(GenericsTest.max(apples).getSize());
    }

    private static <T extends Comparable<T>> T max(Collection<? extends T> coll) {
        T max = coll.iterator().next();

        for (T elm : coll) {
            if (max.compareTo(elm) < 0)
                max = elm;
        }

        return max;
    }
}

代码正在运行而没有? max方法签名中的super T和List属于Apple类型。根据你提到的报价,它应该不起作用。我好像在这里感到困惑......