算法(4th ed)(104):基础——数据抽象 4.5.8

阅读数:12 2019 年 11 月 2 日 12:20

算法(4th ed)(104):基础——数据抽象 4.5.8

(数据类型的设计:等价性)

两个对象相等意味着什么?如果我们用相同类型的两个引用变量 ab 进行等价性测试(a == b),我们检测的是它们的标识是否相同,即引用是否相同。一般用例希望能够检查数据类型的值(对象的状态)是否相同或者实现某种针对该类型的规则。Java 为我们开了个头,为 IntegerDoubleString 等标准数据类型以及一些如 FileURL 的复杂数据类型提供了实现。在处理这些类型的数据时,可以直接使用内置的实现。例如,如果 xy 均为 String 类型的值,那么当且仅当 xy 的长度相同且每个位置的字符均相同时 x.equals(y) 的返回值为 true。当我们在定义自己的数据类型时,比如 DateTransaction,需要重载 equals() 方法。Java 约定 equals() 必须是一种等价性关系。它必须具有:

  • 自反性x.equals(x)true
  • 对称性,当且仅当 y.equals(x)true 时,x.equals(y) 返回 true
  • 传递性,如果x.equals(y)y.equals(z) 均为truex.equals(z) 也将为true

另外,它必须接受一个 Object 为参数并满足以下性质:

  • 一致性,当两个对象均未被修改时,反复调用 x.equals(y) 总是会返回相同的值;
  • 非空性x.equals(null) 总是返回 false

这些定义都是自然合理的,但确保这些性质成立并遵守 Java 的约定,同时又避免在实现时做无用功却并不容易,如 Date 所示。它通过以下步骤做到了这一点。

  • 如果该对象的引用和参数对象的引用相同,返回 true。这项测试在成立时能够免去其他所有测试工作。
  • 如果参数为空(null),根据约定返回false(还可以避免在下面的代码中使用空引用)。
  • 如果两个对象的类不同,返回false。要得到一个对象的类,可以使用getClass() 方法。请注意我们会使用 == 来判断 Class 类型的对象是否相等,因为同一种类型的所有对象的 getClass() 方法一定能够返回相同的引用。
  • 将参数对象的类型从Object 转换到Date(因为前一项测试已经通过,这种转换必然成功)。
  • 如果任意实例变量的值不相同,返回 false。对于其他类,等价性测试方法的定义可能不同。例如,我们只有在两个 Counter 对象的 count 变量相等时才会认为它们相等。

算法(4th ed)(104):基础——数据抽象 4.5.8

在数据类型的定义中重写 `toString()` 和 `equals()` 方法

你可以使用上面的实现作为实现任意数据类型的 equals() 方法的模板。只要实现一次 equals() 方法,下一次就不会那么困难了。

评论

发布