史上最详细equals方法相等机制解析
JAVA重写equals万能公式
重写equals方法的原则
(学到hashmap部分重新重点了解重写equals方法)
java语言规范中要求equals方法具有以下性质
①自反性:非空引用x,x.equals(x)应返回true
②对称性:非空引用x,y,当且仅当x.equals(y)==true时,y.equals(x)==true
③传递性:非空引用x,y,z,若x.equals(y)==true,y.equals(z)==true,则x.equals(z)==true。
④一致性:若x,y引用对象没有改变,则反复调用x.equals(y)应返回相同值。
⑤空引用:x.equals(null) 应返回false
详解重写equals中用instanceof与getClass的区别
考虑e.equals(m),e为Employee对象,m为Manage对象,并且两对象有相同的字段值,若在Employee.equals采用instanceof检测,调用将返回true,当反过来为了满足对称性,需要将manage强制转换,而不考虑manage类的独有字段,这让人感觉instanceof不是那么好。
getClass检测又可能违反替换原则,因为getClass只有在两个对象属于同一个类时才判断相等,但实际上当两个属于不同类的对象的需要比较的字段相等时,我们也可以判定他们相等,因此存在局限性。
总结:两个均存在弊端,getclass用于判断同一类对象是否相等,而instanceof可以处理继承类对象的情况。因此可根据需求选择instanceof或getClass。
下面给出完美的equals编写建议,(实际编写时可简略)
-
先检查
if(this==otherObject) return true.
这是一个优化,先检查地址代价较小。 -
检测otherObject是否为null。
-
如果希望只在同一类中比较相等(主要是子类中有独有字段时),则采用getClass检测
if(!(otherObject.getClass()==this.getClass())) return false;
-
希望在继承层次中比较相等(主要是不考虑子类中的独有字段,只考虑超类的相等性)可以用instanceof检测。
通常用instanceof检测时要进行强制转换。 -
用了instanceof检测,转换后使用==比较类中的字段是否一一对应相等。
例:
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Manager)) return false;
Manager manager = (Manager) o;
return id == manager.id&&Objects.equals(manager.localDate,localDate);
}
Object.equals()方法
用于equals重写很方便