是否有任何可比较的自身不具有可比性?

时间:2014-04-19 21:31:53

标签: java java-8 comparable

Comparable的合同中,没有任何东西强迫对象与自身相比。这只是

  

强烈推荐,但并非严格要求(x.compareTo(y)== 0)==(x.equals(y))

这意味着推荐 x.compareTo(x)不要抛出。但是可以写一个

class X implements Comparable<Y> {
    ...
}

其中XY是两个不相关的类。我看不出它有什么好处,但是在{8}的Java 8版本中,甚至还有相应的检查。

  • 允许使用两个不相关的类实现X implements Comparable<Y>吗?
  • 有意义吗?

我猜答案是肯定的,不是,但这只是猜测

4 个答案:

答案 0 :(得分:4)

Comparable宣传合同,其中比较应与equals保持一致,即(a.compareTo(b) == 0) == a.equals(b)。但它并没有强迫你这样做,任何奇怪的合同都可以强制执行。

所以你可以创建一个:

class DumbInteger implements Comparable<DumbInteger> {
    private final int i;
    public DumbInteger(int i) { this.i = i; }
    public int compareTo(DumbInteger di) { return 0; }
    public boolean equals(Object other) { /* checks */ return other.i == this.i; }
}

你也可以创建一个:

class DumberInteger implements Comparable<String> {
    private final int i;
    public DumberInteger(int i) { this.i = i; }
    public int compareTo(String s) { return 0; }
    public boolean equals(Object other) { /* checks */ return other.i == this.i; }

    public static void main(String[] args) {
        System.out.println(new DumberInteger(0).compareTo("abc"));
    }
}

但这样做可能没有意义。在任何情况下,这都不是特定于Java 8的,因为Comparable接口自Java 2以来一直存在并且在Java 5中“泛化”。

但它可能不是Comparable接口本身的一个缺陷,因为我认为在Java中没有办法创建一个只能通过类实现的通用接口I<T>。属于T的子类型。

答案 1 :(得分:1)

我看到我错过了合同的一部分,也没有看到HashMap.comparableClassFor存在的原因。


合同说明

  

(x.compareTo(y)&gt; 0&amp; y.compareTo(z)&gt; 0)表示x.compareTo(z)&gt; 0

因此只要X大于YY大于X,那么X的两个实例必须与彼此。这并没有留下太多的自由:

  • 其中一个类型为空。这毫无意义。
  • X的所有实例都小于或等于Y的所有实例(或相反的方向)。这略微不那么荒谬。

所以,我总结说这是可能的,但没有任何意义。最简单的例子是

class X implements Comparable<Void> {
    public int compareTo(Void v) {
        return 43; // or throw or whatever, it doesn't matter
    }
}

我想HashMap.comparableClassFor的原因是支持公共超类的不同实现,如

abstract class AByteArray implements Comparable<AByteArray> {}
class SparseByteArray extends AByteArray {...}
class DenseByteArray extends AByteArray {...}

这似乎有道理,甚至可以与平等一致。

答案 2 :(得分:0)

它有意义吗?

将两个类Comparable相互关联的一个问题是因为它将这些类紧密地结合在一起。这使得在另一种情况下难以重用该类。

试过它,可以比较两个不同类的对象。

这是完整的代码 https://gist.github.com/cevaris/11099129

X x = new X();
x.xTest = 10;

Y y = new Y();
y.yTest = 100;

System.out.println("x.compareTo(y) == -1: " + (x.compareTo(y) == -1)); //True
System.out.println("y.compareTo(x) == 1: " + (y.compareTo(x) == 1));   //True

这是Y实现。

class Y implements Comparable<X> {

    int yTest;

    @Override
    public int compareTo(X o) {
        if(this.yTest < o.xTest) return -1;
        if(this.yTest > o.xTest) return 1;
        return 0;
    }

}

这是X实现。

class X implements Comparable<Y> {

    int xTest;

    @Override
    public int compareTo(Y o) {
        if(this.xTest < o.yTest) return -1;
        if(this.xTest > o.yTest) return 1;
        return 0;
    }

}

答案 3 :(得分:0)

好吧,它在技术上是可以完成的(按照 @cevaris' answer)并且当您有多种表示同一对象的方法时可以理解,例如一个对象及其 String 表示。但是,如果您可以两次实现相同的接口,这才有意义:

public class CompInt implements Comparable<CompInt>, Comparable<String> {

但由于 type erasure,Java 中禁止这样做。