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

J_Y*_*Y_C 52 java interface equals tostring hashcode

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

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

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

为什么不对我强制执行?它抱怨如果我没有实现任何其他方法,但它没有强制执行这三个方法.是什么赋予了?有线索吗?

Ste*_*n C 40

听起来你想强制你的类覆盖这些方法的默认实现.如果是这样,那么执行此操作的方法是声明一个抽象超类,该类具有声明为abstract的方法.例如:

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

    public abstract boolean equals(Object other);

    public abstract int hashCode();

    public abstract String toString();
}
Run Code Online (Sandbox Code Playgroud)

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

这种方法有点工作,但它不是一个理想的解决方案.

  • 对于现有的类层次结构可能存在问题.

  • 强制实现现有接口的类扩展特定的抽象类是一个坏主意.例如,您可以更改方法签名中的参数以使用抽象类而不是现有接口.但最终结果是代码灵活性较低.(并且人们可以找到破坏它的方法;例如通过添加他们自己的抽象子类,通过super.<method>(...)调用"实现"方法!)

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


回到您的实际问题,为什么您的界面不强制类重新声明这些方法:

为什么不对我强制执行?它抱怨如果我没有实现任何其他方法,但它没有强制执行这三个方法.是什么赋予了?有线索吗?

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

JLS 8.1.5声明如下:

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


Ada*_*kin 39

Java中的所有对象都继承自,java.lang.ObjectObject提供这些方法的默认实现.

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

您可以通过在界面中提供不同的方法,toPrettyString()或者类似的方法来实现您想要的任何一种方式.然后,您可以调用该方法而不是默认toString()方法.

  • 如果你可以强制执行它,那么覆盖可能只是调用super.hashCode(). (3认同)
  • 这不是继承的目的吗?你为什么想要一个不同的机制? (2认同)
  • 对于matt b,通常定义自己的toString版本,以便在打印对象时得到一致的答案,而不是类名的哈希值,等等。对于hashcode和equals,无论何时使用对象在集合中,哈希码和equals的默认实现并不总是正确地代表您的应用程序“有意义地相等”。 (2认同)

Chs*_*y76 17

这些方法中的所有3个都是java.lang.Object由所有其他类(隐式)扩展定义的; 因此存在这些方法的默认实现,编译器没有什么可抱怨的.


Ste*_*eod 7

任何实现您的接口的类也会扩展Object.Object定义了hashCode,equals和toString,并且具有所有三个的默认实现.

你想要达到的目标是好的,但不切实际.


Tor*_*dek 5

这些方法的实现从一直到来Object.


Boz*_*zho 5

如果要强制重写equals()和hashCode(),请从抽象超类扩展,该超类将这些方法定义为抽象.