繁体   English   中英

有问题<t extends comparable<? super t> ></t>

[英]Problem with <T extends Comparable<? super T>>

我有三个 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 - 语法问题:我应该这样写什么: public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll) public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll) 但它现在工作正常。为什么? Class Apple没有实现Comparable<Apple>并且没有super

[更新]
Java Generics 和 Collections 书上说:

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

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

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

您将无法获得List<Apple>max ,因为Apple没有实现Comparable<Apple> ,它实现了Comparable<Fruit> 但你我都非常清楚, Apple知道如何将自己与另一个Fruit进行比较,因为它继承了该功能。

我们通过将max的声明更改为以下内容来解决此问题:

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

这意味着我们接受任何 class T ,例如:

  1. T implements Comparable<T>或者...
  2. T 为某些X T implements Comparable<X>使得XT的超级 class

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

在第一种情况下,很明显,任何T实例都可以安全地接受T的另一个实例作为其compare(T)方法的参数。

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

您的示例说明了第二种情况,其中T对应于AppleX对应于Fruit

您使用Collections.max(apples)而不是Algorithm.max

Collections.max的声明略有不同:

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

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

我有一个 Fruit 抽象 class (实现 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;
    }
}

然后我有一个苹果扩展水果 class:

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 类型。 根据你提到的报价,它不应该工作。 我似乎在这里感到困惑...

让我们试着看看当你删除 <? 超T>

public class CollectionMinSignature {
    
    public static <T extends Object & Comparable</*? super*/ T>> T min(Collection<? extends T> coll) {
    
        Iterator<? extends T> i = coll.iterator();
        T candidate = i.next();

        while (i.hasNext()) {
            T next = i.next();
            if (next.compareTo(candidate) < 0)
                candidate = next;
        }
        return candidate;
    }
    
    public static class A implements Comparable<A> {
        private int i;
        public A (int i) {
            this.i = i;
        }
        @Override
        public int compareTo(A a) {
            return this.getVal() - a.getVal();
        }
        public String toString() {
            return Integer.toString(i);
        }
        public int getVal() {
            return this.i;
        }
    }
    public static class B extends A {
        public B(int i) {
            super(i);
        }
    }
    
    public static void main(String[] args) {
    
    Collection<B> coll = new ArrayList<B>(List.of(new B(0), new B(1), new B(-1)));
    
    B b = min(coll); /*it doesn't work*/
    B b2 = Collections.min(coll); /*it works*/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM