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

Java 接口中的toString()、equals()和hashCode(),java,interface,equals,hashcode,tostring,Java,Interface,Equals,Hashcode,Tostring,因此,我有一个接口,其中包含一系列需要实现的方法,这些方法的名称是不相关的 实现此接口的对象通常被放入集合中,并且我希望它们使用一种特殊的toString()格式 因此,我认为将hashCode()、equals()和toString()放入接口中会很方便,以确保我记得覆盖这些函数的默认方法。但是当我将这些方法添加到接口时,如果我没有实现这三个方法,IDE/编译器不会抱怨,即使我显式地将它们放在接口中 为什么我不能强制执行?如果我没有实现任何其他方法,它会抱怨,但它没有强制执行这三种方法。有什么

因此,我有一个接口,其中包含一系列需要实现的方法,这些方法的名称是不相关的

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

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


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

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

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

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


实现所需功能的一种方法是在接口中提供不同的方法,例如,
toPrettyString()
或类似的方法。然后您可以调用该方法,而不是默认的
toString()
方法。

这些方法都是从
对象来实现的。

实现接口的任何类都会扩展对象。对象定义hashCode、equals和toString,并具有这三个的默认实现


您试图实现的是好的,但不可行。

您的对象已经包含了这三种方法的实现,因为每个对象都从对象继承这些方法,除非它们被重写。

Java只关心这些方法是在某处定义的。接口不会强制您在新类中重新定义方法,这些新类第一次从接口继承,如果它们已经定义。由于
java.lang.Object
已经实现了这些方法,因此您的新对象符合接口,即使它们没有自己重写这三个方法。

其他人已经充分回答了您的实际问题。至于解决特定问题的方法,您可以考虑创建自己的方法(可能是GestStRePress、GETCuthHashCad和ErraseObjor),并使对象扩展一个基类,其相等、ToShand和Hash码方法调用这些方法。
不过,这可能会首先破坏使用接口的目的。这就是为什么有些人认为equals、toString和hashCode从一开始就不应该包含在对象类中的原因之一。

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

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

    public abstract boolean equals(Object other);

    public abstract int hashCode();

    public abstract String toString();
}
然后将当前类更改为
extend
this class

这种方法是可行的,但不是理想的解决方案

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

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

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


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

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

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

声明如下:

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


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

如果您声明了一个接口,其中默认情况下所有方法都是抽象的,并且您确实需要提供功能,但是当您在子类中实现它时,然后你提供了实现权。 正如您所看到的,每个类都是一个超类的子类(简单地说,对象是sup)
public interface Distinct {
    boolean checkEquals(Object other);
    int hash();
}

public interface Stringable {
    String asString();
}

public abstract class DistinctStringableObject {

    @Override
    public final boolean equals(Object other) {
        return checkEquals();
    }

    @Override
    public final int hashCode() {
        return hash();
    }

    @Override
    public final String toString() {
        return asString();
    }
}
public abstract class MyDistinctStringableObject extends DistinctStringableObject {

    @Override
    public final boolean checkEquals(Object other) {
        ...
    }

    @Override
    public final int hash() {
        ...
    }

    @Override
    public final String asString() {
        ...
    }
}