应该比较另一种类型吗?

我想知道以下是否有一个有效的用例:

class Base {} class A implements Comparable { //... } 

它似乎是一个常见的模式(参见许多例子的集合)来接受类型T的集合,其中T extends Comparable T extends Comparable

但是在比较基类时,在技术上似乎不可能完成compareTo()的约定,因为没有办法确保另一个类不会通过矛盾的比较来扩展基类。 请考虑以下示例:

 class Base { final int foo; Base(int foo) { this.foo = foo; } } class A extends Base implements Comparable { A(int foo) { super(foo); } public int compareTo(Base that) { return Integer.compare(this.foo, that.foo); // sort by foo ascending } } class B extends Base implements Comparable { B(int foo) { super(foo); } public int compareTo(Base that) { return -Integer.compare(this.foo, that.foo); // sort by foo descending } } 

我们有两个类使用不遵循通用规则的比较来扩展Base (如果有一个共同的规则,它几乎肯定会在Base实现)。 然而,以下破坏的排序将编译:

 Collections.sort(Arrays.asList(new A(0), new B(1))); 

仅接受T extends Comparable会不会更安全? 或者是否有一些用例可以validation通配符?

这个问题问得好。 首先,让我们从Collections使用类似方法的原因开始

 binarySearch(List> list, T key) 

的确,为什么不呢

 binarySearch(List> list, T key) 

其原因是PECS原则:Producer Extends,Consumer Super。 binarySearch做什么? 它从列表中读取元素,然后通过它们的值传递compareTo函数来比较它们。 由于它读取元素,因此列表充当生产者,因此第一部分 – 生产者扩展。 这一点很明显,那么消费者超级部分呢?

Consumer Super基本上意味着如果你只是将值传递给某个函数,你并不关心它是否接受你的对象的确切类型或它的某些超类。 所以binarySearch声明所说的是:只要可以将任何内容传递给列表元素的compareTo方法,我就可以查找任何内容。

在排序的情况下,它并不那么明显,因为元素只是相互比较。 但即便如此,如果Base实际实现Comparable (并进行整个比较), AB只是扩展Base而不用任何方式触及比较,该怎么办? 那么您将无法对AB列表进行排序,因为它们分别不实现ComparableComparable 。 每次子类化时都必须重新实现整个接口!

另一个例子:如果有人想在包含某些类甚至不扩展Base实例的列表上进行二进制搜索,该怎么办?

 class BaseComparable implements Comparable { private final Base key; // other fields BaseComparable(Base key, ...) { this.key = key; // other fields initialization } @Override public int compareTo(Base otherKey) { return this.key.compareTo(otherKey); } }; 

现在他们想要使用A的实例作为这个二进制搜索的关键。 他们只能这样做? super T ? super T部分。 请注意,此类不知道密钥是A还是B因此无法实现Comparable

至于你的例子,我想这只是一个糟糕设计的例子。 不幸的是,在没有违反PECS原则和/或限制Javagenerics的function已经有限的情况下,我认为无法阻止此类事情。