重写equals需要满足下面5个性质
自反性:x.equals(x) --> true
对称性:x.equals(y) --> true 则 y.equals(x) --> true
传递性:x.equals(y)–>true, y.equals(z)–>true, 则 x.equals(z)–>true
一致性:x.equals(y)在x,y没有变化的情况下,多次调用结果不变
非空性:x.equals(null)–>false
建议
- 显式参数命名为otherObject,稍后需要转化
- 检测this与otherObject是否是同一对象
if (this == otherObject) return true; - 检测otherObject是否是null
if(otherObject == null) return false; - 检测是否属于同一个类
if(getClass() != otherObject.getClass()) return false; // getClass 会返回类的完整类名(带包)
如果所有的子类都拥有统一的语义(属性域), 就使用instanceof
if(!(otherObject instanceof ClassName)) return false; - ClassName other = (ClassName) otherObject;
- 比较各字段是否相等
为何只有在拥有统一语义时才能使用instanceof
举例
class Employee {
private name;
private age;
······
}
class Manager extends Employee {
private ele1; // 此类特有字段
}
if(!(otherObject instanceof ClassName)) return false;
e.equals(m)
// 这里e为Employee的实例
// m为Manager的实例
// 假设 e,m的公有字段相等,则-->true // 对Employee来说只需要比较name,age
// 根据对称性,则我们Manager必须设置出使得m.equals(e)-->true的代码(根据对称性,不可抛出异常)
// 按道理来说需要比较name,age,ele1;可是Employee没有ele1
// 这就意味着 Manager 在比较是必须放弃自己的特有字段 ele1 才可以保证-->true, (这不合理)
// 如果这样当我们有m1,m2是只要name,age相同,无论ele1如何,-->true
// 这并不合理。所以我们规定语义不同的子类之间比较使用getClass, 即非同一子类的实例 --> false;