简体   繁体   English

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

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

I have a three class: 1.class Algorithm having max() finding maximum value in a Collection :我有三个 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 : 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 extending Fruit : 3.class Apple延长Fruit

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

Now the question is this:现在的问题是:

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);
    }
}

According to this post Java - Syntax Question: What is I should wrote it this way: public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll)根据这篇文章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) . public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll) But it is working fine now.Why?但它现在工作正常。为什么? Class Apple does not implement Comparable<Apple> and there is no super . Class Apple没有实现Comparable<Apple>并且没有super

[UPDATE] [更新]
Java Generics and Collections Book says: Java Generics 和 Collections 书上说:

Without the super wildcard, finding the maximum of a List<Apple> would be illegal, even though finding the maximum of a List<Fruit> is permitted.如果没有super通配符,查找List<Apple>的最大值将是非法的,即使查找List<Fruit>的最大值是允许的。

Suppose we changed the max method to this:假设我们将max方法更改为:

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

You would not be able to get the max of a List<Apple> because Apple does not implement Comparable<Apple> , it implements Comparable<Fruit> .您将无法获得List<Apple>max ,因为Apple没有实现Comparable<Apple> ,它实现了Comparable<Fruit> But you and I know perfectly well that an Apple knows how to compare itself to another Fruit because it inherited that functionality.但你我都非常清楚, Apple知道如何将自己与另一个Fruit进行比较,因为它继承了该功能。

We fix the problem by changing the declaration of max to this:我们通过将max的声明更改为以下内容来解决此问题:

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

This means that we accept any class T such that:这意味着我们接受任何 class T ,例如:

  1. T implements Comparable<T> , or... T implements Comparable<T>或者...
  2. T implements Comparable<X> for some X such that X is a super class of T T 为某些X T implements Comparable<X>使得XT的超级 class

In order to find the max , we must be sure that any instance of T can safely accept another instance of T as an argument to its compare method.为了找到max ,我们必须确保T的任何实例都可以安全地接受T的另一个实例作为其compare方法的参数。

In the first scenario, it is obvious that any instance of T can safely accept another instance of T as an argument to its compare(T) method.在第一种情况下,很明显,任何T实例都可以安全地接受T的另一个实例作为其compare(T)方法的参数。

In the second scenario, any instance of T can safely accept another instance of T as an argument to its compare(X) method because all instances of T are also instances of X .在第二种情况下,任何T实例都可以安全地接受T的另一个实例作为其compare(X)方法的参数,因为T的所有实例也是X的实例。

Your example illustrates the second scenario, where T corresponds to Apple and X corresponds to Fruit .您的示例说明了第二种情况,其中T对应于AppleX对应于Fruit

You use Collections.max(apples) instead of Algorithm.max .您使用Collections.max(apples)而不是Algorithm.max

Collections.max has slightly different declaration: Collections.max的声明略有不同:

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

sorry for bringing this back but I think it's important.很抱歉把它带回来,但我认为这很重要。 Has your code stopped working properly when changed from Collections.max() to Algorithm.max()?从 Collections.max() 更改为 Algorithm.max() 时,您的代码是否停止正常工作? I've done a simmilar test in jdk8 and I don't understand why it's working fine while according to Java Generics and Collections it should not.我在 jdk8 中进行了类似的测试,但我不明白为什么它可以正常工作,而根据 Java Generics 和 Collections 它不应该。

I have a Fruit abstract class (implementing Comparable):我有一个 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;
    }
}

Then I have a Apple extending Fruit class:然后我有一个苹果扩展水果 class:

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

And finally:最后:

 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;
    }
}

The code is working while there is no?代码在没有的情况下工作? super T in the max method's signature and the List is of Apple type. max 方法的签名中的 super T 和 List 是 Apple 类型。 According to the quote you mentioned it shouldn't be working.根据你提到的报价,它不应该工作。 I seem to be puzzled here...我似乎在这里感到困惑...

let's try to see what happens when you remove <?让我们试着看看当你删除 <? super T>超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