[英]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 aList<Apple>
would be illegal, even though finding the maximum of aList<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
,例如:
T implements Comparable<T>
, or... T implements Comparable<T>
,或者...T implements Comparable<X>
for some X
such that X
is a super class of T
X
T implements Comparable<X>
使得X
是T
的超级 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
对应于Apple
, X
对应于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.