java语言规范对equals的要求:
1.自反性:任意非空引用x,x.equals(x)为true
2.对称性:对任意引用想x、y,当且仅当y.equals(x)为true,x.equals(y)也为true
3.传递性:对任意引用x、y、z,若x.equals(y)为true,y.equals(z)为true,则x.equals(z)也为true
4.一致性:x、y引用未发生变化时,x.equals(y)反复调用结果一致
5.任意非空引用x,x.equals(null)为false
编写一个完美的equals方法的建议:
(1)显示参数命名为otherObject,之后需要转化成other
(2)检测this与otherObject是否引用同一个对象 if(this == otherObject) return true
(3)检测otherObject是否为null if(otherObject == null) return false
(4)比较this与otherObject是否属于同一个类,若equals的语义在子类中有所改变则用getClass检测 if(getClass() != otherObject.getClass()) return false; 若语义统一,则使用instanceof检测 if(!(otherObject instanceof ClassName)) return false;
(5)将otherObject转为相应类的变量ClassName other = (ClassName)otherObject;
(6)开始对所有需要比较的域进行比较。使用==比较基本类型域,使用equals比较对象域,所有域都匹配则返回true,否则返回false
return field1 == other.field1 && Objects.equals(field2,other.field2) && …
如果子类中重新定义equals,就要调用super.equals(other)。对于数组类型的域,可以使用静态的Arrays.equals()方法检测相应的数组元素是否相等
@Override public boolean equals(Object other) 参数如果不是Object类型会报错
A是B的子类,A中的equals()先调用父类,在对比子类的实力域
if(!super.equals(otherObject)) return false
…
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
/if (hireDate == null) {
if (other.hireDate != null)
return false;
} else if (!hireDate.equals(other.hireDate))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
return false;
return true;/
return Objects.equals(name, other.name) && salary == other.salary && Objects.equals(hireDate,other.hireDate);
hashCode方法
散列码是由对象导出一个整型值,散列码是没有规律的。hashCode方法定义在Object类中,因此每个对象有一个默认的散列码,其值为对象的存储地址。重新定义equals方法就需要重新定义hashCode方法。equals与hashCode的定义必须一致:如果x.equals(y)返回true,那么x.hashCode()就必须与y.hashCode()具有相同的值。
hashCode的一种简单实现方法
public int hashCode(){
return Object.hash(field1,field2,field3,…);
}
子类对象的hashCode()
Emplyoee已有hashCode()方法,Manager作为Employee的子类:
public int hashCode() {
return super.hashCode()+ 17new Double(bonus).hashCode();
/
final int prime = 31;
int result = super.hashCode();
long temp;
temp = Double.doubleToLongBits(bonus);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;*/
}
如果存在数组类型的域,那么可以使用静态的Arrays.hashCode方法计算一个散列码,这个散列码由数组元素的散列码组成。
学习自java核心技术 卷I