为什么不在接口Comparator中实现所有方法?

5
今天,我尝试学习Java 8中的一些特性,具体涉及Lambda表达式。我创建了一个新的比较器,如下所示:
Comparator<String> strCom = new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return 0;
    }
};

当我阅读Comparator接口内的代码时,我感到困惑。虽然接口Comparator有两个方法compare()和equals(),但我们不需要实现它们全部。我已经找到了一些原因,为什么我们不需要实现方法equals()这里。但我也在javadocs中读到:
"If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile". 什么是接口? 所以,有人可以帮助我理解吗?不重写equals()仍然是合法的吗?

如果你想知道两个比较器是否相等,你可以重写equals方法。 - SomeJavaGuy
Note that it is always safe not to override Object.equals(Object). However, overriding this method may, in some cases, improve performance by allowing programs to determine that two distinct comparators impose the same order. - biziclop
请参见:https://dev59.com/OHjZa4cB1Zd3GeqPdWEo - user85421
2个回答

4
由于在Java中一切皆是对象,所以不需要实现equal方法,因为它已经从Object类继承了过来。
正如文档中所示,equal方法已经在Object类中定义:https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html 只有在想要检查两个比较器是否具有相同的数据并且是“相等”的情况下,才需要实现equals方法,但这可能不是您寻找的内容,因为比较器通常不持有任何实例变量。

1
Javadoc 表示,如果两个比较器施加相同的对象排序,则它们“相等”。因此,equals() 的行为仅取决于 compare() 方法的行为 - 不涉及任何实例变量。 - Klitos Kyriacou
如果您有两个相同类的比较器实例,它们的行为只有在它们的实例变量也不同时才会有所不同。(除非您正在做一些非常糟糕的事情,例如基于它们运行的线程或外部全局变量来确定行为。)@KlitosKyriacou - biziclop
@biziclop 不需要任何实例变量(通常比较器没有实例变量,尽管有些有)。两个比较器可以是不同的类,都实现了比较器接口。如果它们各自的compare()方法对于任何给定的参数始终返回相同的值,则它们将被视为相等。换句话说,即使它们是不同的类,两个相等的比较器也是可互换的。 - Klitos Kyriacou
@KlitosKyriacou 很多我的比较器确实有实例变量。在实践中,这种情况比你想象的要更常见,而不同类别的两个比较器产生相同顺序的可能性非常小。然而,关键是如果它们属于同一类,但行为仍然不同,往往是因为它们的实例变量。 - biziclop

3
该教程试图通过一个简单的例子介绍接口的概念,但最终导致了误导。
以这段代码为例:
public interface MyInterface {
    public void foo();
    public void bar();
}

public class Super {
    public void foo() { System.out.println("foo"); }
}

public class Sub extends Super implements MyInterface {
    public void bar() { System.out.println("bar"); }
}

这是完全有效的代码,尽管 Sub 仅明确实现了 MyInterface 中的一个方法。很容易看出这是有效的: foo() 已经由 Super 实现,并且该实现被 Sub 继承。
具体规则如此处所述

除非正在声明的类是抽象类,否则必须通过在此类中声明或通过从直接超类或直接超接口继承的现有方法声明来实现每个直接超接口的所有抽象成员方法(§8.4.8.1),因为不允许具有抽象方法的类是不抽象的(§8.1.1.1)。

虽然规则只涉及直接超类,但技术上也适用于间接超类,因为方法继承透过整个层次结构。
鉴于 equals() 已由 Object 实现,而 Object 是每个类的直接或间接超类,因此您不必提供 equals() 的实现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接