[英]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
,例如:
T implements Comparable<T>
,或者...X
T implements Comparable<X>
使得X
是T
的超級 class 為了找到max
,我們必須確保T
的任何實例都可以安全地接受T
的另一個實例作為其compare
方法的參數。
在第一種情況下,很明顯,任何T
實例都可以安全地接受T
的另一個實例作為其compare(T)
方法的參數。
在第二種情況下,任何T
實例都可以安全地接受T
的另一個實例作為其compare(X)
方法的參數,因為T
的所有實例也是X
的實例。
您的示例說明了第二種情況,其中T
對應於Apple
, X
對應於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.