[英]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.