簡體   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