接口中的 toString()、equals() 和 hashCode()

2022-08-31 16:03:25

所以,我有一个接口,里面有一堆需要实现的方法,方法名称是无关紧要的。

实现此接口的对象通常放入集合中,并且还具有我希望它们使用的特殊 toString() 格式。

所以,我认为将hashCode(),equals()和toString()放入接口中会很方便,以确保我记得覆盖这些的默认方法。但是,当我将这些方法添加到接口中时,如果我没有实现这三种方法,即使我显式地将它们放在接口中,IDE/编译器也不会抱怨。

为什么这不会对我强制执行?如果我不实现任何其他方法,它就会抱怨,但它没有强制执行这三种方法。什么原因?有什么线索吗?


答案 1

这听起来像是要强制类重写这些方法的默认实现。如果是这样,执行此操作的方法是声明一个抽象超类,该超类将方法声明为抽象。例如:

public abstract class MyBaseClass implements ... /* existing interface(s) */ {

    public abstract boolean equals(Object other);

    public abstract int hashCode();

    public abstract String toString();
}

然后将当前类更改为此类。extend

这种方法有点有效,但它不是一个理想的解决方案。

  • 对于现有的类层次结构来说,这可能是有问题的。

  • 强制实现现有接口的类扩展特定的抽象类是一个坏主意。例如,可以将方法签名中的参数更改为使用抽象类而不是现有接口。但最终结果是代码的灵活性降低。(无论如何,人们都可以找到颠覆这一点的方法;例如,通过添加自己的抽象子类,通过调用来“实现”方法!super.<method>(...)

  • 强加特定的类层次结构/实现模式是短视的。您无法预测未来的某些需求更改是否意味着您的限制会导致困难。(这就是为什么人们建议针对接口而不是特定类进行编程。


回到你的实际问题,为什么你的接口不强迫一个类重新声明这些方法:

为什么这不会对我强制执行?如果我不实现任何其他方法,它就会抱怨,但它没有强制执行这三种方法。什么原因?有什么线索吗?

接口施加了一个约束,即实现它的具体类具有每个方法的实现。但是,它不要求类本身提供这些方法。方法实现可以从超类继承。在这种情况下,这就是正在发生的事情。从 saftisfy 继承的方法受约束。java.lang.Object

JLS 8.1.5 声明如下:

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


答案 2

Java 中的所有对象都继承自 和 Object 提供这些方法的缺省实现。java.lang.Object

如果您的接口包含其他方法,如果您没有通过提供这些方法的实现来完全实现接口,Java 将会抱怨。但是在 的情况下,和(以及您没有提到的其他一些)实现已经存在。equals()hashCode()toString()

一种方法可能是通过在界面中提供不同的方法,或者类似的东西。然后,您可以调用该方法而不是默认方法。toPrettyString()toString()