java对象的等价性

如果用相同类型的两个引用变量a 和b 进行等价性测试(a ==b),检测的是它们的标识是否相同,即引用是否相同。

一般用例希望能够检查数据类型的值(对象的状态)是否相同或者实现某种针对该类型的规则。

Java 为Integer、Double和String 等标准数据类型以及一些如File 和URL 的复杂数据类型提供了实现。

在处理这些类型的数据时,可以直接使用内置的实现。

例如,如果x 和y 均为String 类型的值,那么当且仅当x和y 的长度相同且每个位置的字符均相同时x.equals(y) 的返回值为true。

当在定义自己的数据类型时,比如Date 或Transaction,需要重载equals() 方法。

Java 约定equals() 必须是一种等价性关系。它必须具有:
  自反性,x.equals(x)为true;
  对称性,当且仅当y.equals(x)为true时,x.equals(y)返回true;
  传递性,如果x.equals(y)和y.equals(z)均为true,x.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 变量相等时才会认为它们相等。

public class Date
{
private final int month;
private final int day;
private final int year;
public Date(int m, int d, int y)
{ month = m; day = d; year = y; }
public int month()
{ return month; }
public int day()
{ return day; }
public int year()
{ return year; }
public String toString()
{ return month() + "/" + day() + "/" + year(); }
public boolean equals(Object x)
{
if (this == x) return true;
if (x == null) return false;
if (this.getClass() != x.getClass()) return false;
Date that = (Date) x;
if (this.day != that.day) return false;
if (this.month != that.month) return false;
if (this.year != that.year) return false;
return true;
}
}

posted @ 2020-08-02 22:25  konqlan  阅读(329)  评论(0)    收藏  举报