Java:使用 toString().equals() 与 equals()

Java: Use toString().equals() vs. equals()

这是一个理论问题。我有一个自己设计的对象,其中包含一堆变量、方法等。我覆盖了 toString 方法,主要用于记录目的,将变量的值设为 return。在我看来,比较此对象的实例的最简单和最直接的方法是比较从 toString 方法获得 returned 的内容。例如,equals 方法可能看起来像

public boolean equals(MyObject instance)
{
   return toString().equals(instance.toString());
}

有什么理由不这样做吗?

避免这种模式的一个原因是速度:为了使用 toString() 比较相等性,您必须这样做:

  • 为对象this
  • 创建临时String对象
  • 为对象instance
  • 创建临时String对象
  • 比较第一个 String 和第二个 String 个字符
  • 使临时字符串可用于垃圾检测

如果直接进行比较,则可以跳过大部分内容。例如,直接比较 ints 需要比较 4 个字节,而比较它们的字符串表示最多需要 9 个字节的比较。其他数据类型也会出现类似情况。

dasblinkenlight 简要总结了性能原因导致您无法执行您要求的操作。

避免这种模式的另一个重要原因与 toString() 方法的一般契约有关。 class 对象的所有可覆盖方法都有一个 通用契约 。因为这些方法由您在 Java 中定义的每个 class 继承,并且因为它们在许多自定义 class 中经常被覆盖,所以了解并遵守它们的一般契约非常重要。

toString() 的一般契约是对象方法中最简单的:

Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method.

没有要求 toString() 返回的字符串符合特定格式,也没有要求您必须指定作为 API.[=22 的一部分返回的字符串的格式=]

正因为如此,toString() 返回的对象的字符串表示最常见的是 实现细节,它可以从您的 class到下一个。如果您基于它们进行相等比较,更改 toString() 返回的字符串表示可能会导致程序失败。

不基于 toString() 方法进行相等比较的另一个原因是这样做不会为您的 class 提供所需的基础结构,因此它可以与 Java 一起使用集合框架。 Java 集合 classes 需要格式正确的 equals()hashCode() 方法来存储其中的对象才能正常工作:

  • 如果您正在编写的 class 有任何机会用于任何 Java 集合框架 classes and/or它可能被其他程序员使用,编写格式良好的 equals()hashCode() 方法是值得的。

  • 因为任何格式合理的 equals() 方法的性能都将超过基于 toString() 的字符串比较的性能......并且由于许多 classes 无论如何都应该有一个格式正确的 equals() 方法......你也可以继续使用自定义 equals() 方法。