Java equals、hashcode和toString方法
一、Java规范对于equals方法特性的要求
- 自反性:对于非空引用x,x.equals(x)应该返回true。
- 对称性:对于任何引用x和y,当且仅当y.equals(x)返回true,x.equals(y)也应该返回true。
-
传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,x.equals(z)也应该返回true。
- 一致性:如果x和y引用的对象没有发生变化,反复调用x.eqimIs(y)应该返回同样的结果。
-
对于任意非空引用x,x.equals(null) 应该返回false。
对于对称性,当参数不是同一个类时,但是存在继承关系时,需要格外注意。如果子类能够拥有自己的相等概念,则对称性需求将强制采用 getClass 进行检测。如果由超类决定相等的概念,那么就可以使用 intanceof 进行检测,这样可以在不同子类的对象之间进行相等的比较。
二、编写一个完美的 equals 方法的建议:
- 显式参数命名为 otherObject。
- 检测this与otherObject是否引用同一个对象:
这条语句只是一个优化。实际上,这是一种经常采用的形式。因为计算这个等式要比一个一个地比较类中的域所付出的代价小得多。
if (this=otherObject) return true;
- 检测otherObject是否为null, 如果为null, 返回false。这项检测是很必要的。
if(otherObject=null) return false;
- 比较this与otherObject是否属于同一个类。如果equals的语义在每个子类中有所改变,就使用getClass检测:
如果所有的子类都拥有统一的语义,就使用 instanceof 检测:
if (getClass()!=otherObject.getClass()) return false;
if (!(otherObject instanceof ClassName)) return false;
- 将 otherObject 转换为相应的类类型变量:
ClassName other=(ClassName)otherObject;
- 现在开始对所有需要比较的域进行比较了。使用=比较基本类型域,使用 equals 比较对象域。如果所有的域都匹配, 就返回 true; 否 则 返 回 false。对于数组类型的域, 可以使用静态的 Arrays.equals 方法检测相应的数组元素是否相等。
return fieldl==other.field && Objects.equa1s(fie1d2, other.field2)
&& ...;如果在子类中重新定义 equals, 就要在其中包含调用 super.equals(other)。
三、hashCode方法
散列码(hash code)是由对象导出的一个整型值。散列码是没有规律的。如果 x 和 y 是两个不同的对象, x.hashCode() 与 y.hashCode() 基本上不会相同。由于hashCode方法定义在 Object 类中,因此每个对象都有一个默认的散列码,其值为对象的存储地址。
如果重新定义equals方法,就必须重新定义hashCode方法,以便用户可以将对象插人到散列表中。equals与hashCode的定义必须一致:如果x.equals(y)返回 true,那么 x.hashCode()就必须与y.hashCode()具有相同的值。
public int hashCode() { return 7 * Objects.hashCode(name) + 11 * Double.hashCode(salary) + 13 * Objects.hashCode(hireDay);
//Arrays.hashCode
}
四、toString方法
数组继承了 object 类的 toString 方法,数组类型将按照旧的格式打印。例如:
int[] luckyNumbers = { 2, 3, 5, 7, 11, 13 } ; String s = "" + luckyNumbers;
会生成字符串:[I@la46e30(前缀 [I 表明是一个整型数组),修正的方式是调用静态方法Arrays.toString。要想打印多维数组则需要调用Arrays.deepToString方法。

浙公网安备 33010602011771号