如果参数是同一个接口的不同实现,compareTo()返回什么?

时间:2018-05-18 11:47:51

标签: java interface comparable

有界面

alert-purple

和2个班级

/* add a new purple custom color */
$theme-colors: (
  purple: $purple
);

interface Animal extends Comparable<Animal> {
}

当争论与class Dog implements Animal { } 的具体实施不同时,class Cat implements Animal { } 应该返回什么?

它应该抛出compareTo(Animal o)吗?

例如,如果我将Animal实例传递给IllegalArgumentException。我无法比较它们,因为它们是不同的类型。我不能引用Dog,因为他们的超级Cat.compareTo()类型没有实现super.compareTo()。将Object投射到Comparable会抛出Dog

5 个答案:

答案 0 :(得分:5)

如果你不希望它的子类可以相互比较,那么

interface Animal不应该首先实现Comparable<Animal>

来自 Effective Java 2nd Ed 的相关引用,在第8项“考虑实现Comparable”(我从my answer to this question复制以下内容中的大部分内容):

  

compareTo合同中这三条规定的一个后果是由...强制进行的等式测试   compareTo方法必须遵守equals合同施加的相同限制:   反身性,对称性和传递性。因此,同样的警告适用:   没有办法使用新的值组件扩展可实例化的类   保留compareTo合同,除非你愿意放弃   面向对象的抽象(第8项)。

所以,这说明如果您的子类没有比用于确定排序的超类更多的值,那么实现Comparable<Supertype>是合理的。

除了Comparable的一般要求之外,其含义是Comparable<Superclass>应该在Superclass和所有子类中以相同的方式实现。

答案 1 :(得分:2)

Ainimal定义为:

interface Animal extends Comparable<Animal> {
}

您说任何Animal都可以与另一个Animal进行比较。

如果您只想将DogDog进行比较,则应按以下方式定义:

interface Animal {
}

class Dog implements Animal, Comparable<Dog> {

    @Override
    public int compareTo(Dog o) {
        ...
    }
}

答案 2 :(得分:0)

comparable接口仅说明如何与'equals'一起工作,例如,如果compateTo()返回0,则equals应返回0。 https://docs.oracle.com/javase/8/docs/api/index.html?java/lang/Comparable.html

所以实际上它取决于。 如果它对您的程序有意义,您可以转换为Animal

int compareTo(Dog o)
{
    Animal other = (Animal) o;
    ...
}

因此,如果您想使用compareTo对Google的大小或搜索结果数量进行排序,这将是一个有效的实现。

答案 3 :(得分:0)

这取决于你是否想要比较一只猫和一只狗。从广义上讲,有不同的可能性

  1. 将所有Animal实例与与Equal

    一致的订单进行比较 例如,你可以使用不同的动物属性,使2种不同的动物不能拥有相同的所有属性。如果有意义,您可以使用类名作为这样的属性来比较具有相同所有其他属性的Cat和Dog

  2. 将所有Animal实例与与Equal

    不一致的订单进行比较

    上面稍微有点变化:如果两个动物的属性相同,则比较等于,即使它们之间的equals将返回false。请注意,根据Javadoc Comparable

    ,它可能是危险的(即使可能)
      

    强烈建议(尽管不要求)自然排序与equals一致。这是因为没有显式比较器的有序集(和有序映射)在与自然顺序与equals不一致的元素(或键)一起使用时表现得“奇怪”。特别是,这样的有序集(或有序映射)违反了集合(或映射)的一般契约,它是根据等于方法定义的。

  3. 仅比较一个类(当然还有它的子类)中的Animal实例。在这种情况下,应该更改接口声明以使用泛型:

    interface Animal<T> extends Comparable<T> {
    }
    

    和2个班级

    class Dog implements Animal<Dog> {
    
    }
    

    class Cat implements Animal<Cat> {
    
    }
    

答案 4 :(得分:-1)

它应该抛出不匹配错误,如果可能的话,在比较之前使用instanceOf运算符匹配相关对象。