重写Object.equals()总结
equals()规范,假设对象都不为null:
- 自反性:x.equals(x)=true
- 对称性:x.equals(y)=y.equals(x)
- 传递性:x.equals(y) and y.equals(z) = x.equals(z)
- 一致性:当x与y对象内容未改变时,x.equals(y)的值永远不变
- 非空性:x.equals(null)=false
重写equals()分为5步:
- this==obj判断若是同一引用则肯定相等直接返回true
- obj==null判断obj为null直接返回false(因为能调用equals就表明this不为null,两者不相等)
- getClass或者instanceof判断是否属于同一类(涉及继承需分情况选择)
- 将obj强制转换为当前类
- 对比各个域的值是否相等(若成员是对象则应该使用Objects.equals(Field1,Field2)来判断是否相等,避免其中有一个是null造成的异常)
@Override public boolean equals(Object o) { // 1.判断是否同一引用 if (this == o) return true; // 2.如果传入的对象为null返回false if (o == null)return false; // 3.判断是否同一类 if (!(o instanceof User)) return false; // 4.转换为当前类 User user = (User) o; // 5.比较各个字段 return getAge() == user.getAge() && Objects.equals(getName(), user.getName()); }
举例:Manager类(int bonus;String sex),Person类(String name)
getClass与instanceof对比:getClass判断精确某一类,instanceof可以是父类或接口
getClass:精确判断对象的类型
instanceof:判断是否是某类型,可以是父类或者接口
Manager instanceof Person ->true(Manager也是Person)
Person instanceof Manger->false(不是每个Person都是Manager)
1.没有继承Person类,直接继承Object类
个人定义equals的意义,任意选择getClass或instanceof来实现第三步:对比是否属于同一类
@Override public boolean equals(Object obj) { //1.如果引用相同的对象直接返回true if(this==obj)return true; //2.因为能够调用equals则表明this不为null,所以如果obj为null,直接返回false if(obj==null)return false; //3.判断是否同一类 if(getClass()!=obj.getClass())return false; if(!(obj instanceof Manager))return false; //4.将obj强制类型转换为当前类型 Manager object=(Manager)obj; //5.调用父类对象的equals与子类特有域一一对比,因为对象域如String要使用equals必须确保不为null所以要采用Objects.equals(field1,field2)来对比 return Objects.equals(this.sex,object.sex) &&this.bonus==object.bonus; }
2.继承Person类
2.1若是子类Manager有自己的相等概念定义,则强制使用getClass来确保类型精确相等
@Override public boolean equals(Object obj) { //1.如果引用相同的对象直接返回true if(this==obj)return true; //2.因为能够调用equals则表明this不为null,所以如果obj为null,直接返回false if(obj==null)return false; //3.判断类型相等 if(getClass()!=obj.getClass())return false;//4.将obj强制类型转换为当前类型 Manager object=(Manager)obj; //5.调用父类对象的equals并且子类特有域一一对比,因为对象域如String要使用equals必须确保域参数如this.sex不能为null所以要采用Objects.equals(field1,field2)来对比 return super.equals(obj) &&Objects.equals(this.sex,object.sex) &&this.bonus==object.bonus; }
2.2若是由父类Person定义相等的概念,则应该在父类重写equals方法,将该方法设为final使得子类不能重写,然后使用instanceof进行检测,这样Person的不同子类之间都可以比较;
@Override public final boolean equals(Object obj) { //1.如果引用相同的对象直接返回true if(this==obj)return true; //2.因为能够调用equals则表明this不为null,所以如果obj为null,直接返回false if(obj==null)return false; //3.精确要求类型相等 if(getClass()!=obj.getClass())return false; //3.判断类型是否相等(同一继承链) if(!(obj instanceof Person))return false; //4.将obj强制类型转换为当前类型 Person object=(Person) obj; //5.调用父类对象的equals与子类特有域一一对比,因为对象如String要使用equals必须确保域参数不为null否则抛出NullPointer错误,所以要采用Objects.equals(field1,field2)来对比 return Objects.equals(Field,Field) }
数组equals()
Arrays.equals(type[] array1,type[] array2)
重写了equals()就必须重写其hashcode():
https://www.cnblogs.com/ming-szu/p/9158394.html
-----参考<Java 核心技术 卷I>P166