【问题标题】:Why don't implement all method in interface Comparator?为什么不在接口 Comparator 中实现所有方法?
【发布时间】:2016-11-22 12:17:10
【问题描述】:

今天,我正在尝试学习 Java 8 中的一些特性,特别是关于 Lambda 表达式。我像这样创建一个新的 Comaparator :

Comparator<String> strCom = new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return 0;
    }
};

当我在 Comparator 界面中阅读代码时,我感到很困惑。虽然接口Comparator有两个方法compare()equals(),我们不需要全部实现。我找到了我们不需要实现方法 equals() here 的一些原因。但我也读过 javadocs

如果您的类声称实现了一个接口,则该接口定义的所有方法都必须出现在其源代码中,然后该类才能成功编译What Is an Interface?

那么,有人可以帮我理解这一点吗?不覆盖 equals() 仍然合法吗?

【问题讨论】:

  • 如果你想知道两个比较器是否相等,你可以覆盖equals
  • 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.

标签: java comparator


【解决方案1】:

equal 不需要实现,因为它继承自 Object 类,Java 中的一切都是 Object

正如您在文档中所见,Object 类中已经定义了 equal 方法: https://docs.oracle.com/javase/7/docs/api/java/lang/Object.html

如果您想检查两个比较器是否具有相同的数据并因此“相等”,您只需要实现 equals 方法,但这可能不是您想要的,因为比较器通常不保存任何实例变量

【讨论】:

  • Javadoc 说如果两个比较器强加相同的对象顺序,则它们是“相等的”。所以 equals() 的行为仅取决于 compare() 方法的行为 - 不涉及实例变量。
  • @KlitosKyriacou 如果您有同一个类的两个比较器实例,那么只有当它们的实例变量也不同时,它们的行为才会不同。 (除非你正在做一些非常糟糕的事情,比如基于他们正在运行的线程或外部全局变量的行为。)
  • @biziclop 不,您根本不需要任何实例变量(比较器通常没有实例变量,尽管有些有)。两个比较器可能属于不同的类,都实现了比较器接口。如果它们各自的 compare() 方法总是为任何给定参数返回相同的值,则它们将被视为相等。换句话说,两个相等的比较器是可以互换的,即使它们是不同的类。
  • @KlitosKyriacou 我的很多比较器确实都有实例变量。在实践中,它发生的频率比你想象的要多,而不同类的两个比较器产生相同顺序的情况非常罕见。但关键是,如果它们属于同一个类并且它们的行为仍然不同,这通常是因为它们的实例变量。
【解决方案2】:

本教程试图通过一个简单的例子来介绍接口的概念,但最终会产生误导。

以这段代码为例:

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 仅显式实现了MyInterfaces 方法之一。很容易看出为什么这是有效的:foo() 已经由Super 实现,并且该实现由Sub 继承。

确切的规则类似于this:

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

虽然该规则仅涉及直接超类,但在技术上也适用于间接超类,因为方法继承在层次结构中向下冒泡。

鉴于equals()Object 实现并且Object 是每个类的直接或间接超类,您不必为equals() 提供实现。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    • 2019-08-19
    • 2020-06-07
    • 1970-01-01
    相关资源
    最近更新 更多