前言:
- equals方法是一个Object方法
- 覆盖equals方法的代价比较高,最简单的方法就是不去覆盖equals方法
- 如果不覆盖equals方法则类的每个实例只和自身相等
等价关系:
- 自反性:对于任何非null的引用x,x.equals(x)必须返回true。
- 对称性:对于任何非null的引用值x和y,当且仅当y.equals(x)返回true时,x.equals(y)必须返回true。
- 传递性:对于任何非null的引用值x、y和z,如果x.equals(y)返回true,并且y.equals(z)也返回true,那么x.equals(z)也必须返回true。
- 一致性:对于任何非null的引用值x和y,只要equals的比较操作在对象的所用信息没有改变,多次调用x.equals(y),就会一致地返回true,或者一致地返回false。
- 非空性:对于任何非null的引用值x,x.equals(null)必须返回false。
实现高质量的equals方法的诀窍
- 使用==操作符检查“参数是否为这个对象的引用”
- 使用instanceof操作符检查“参数是否是正确的类型”
- 使用参数转换为正确的类型
- 对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配
示例代码:
class MyPoints{
private int x;
private int y;
public MyPoints(int x,int y ){
this.x=x;
this.y=y;
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
@Override
public boolean equals(Object o){
if(o==this)//使用==操作符检查“参数是否为这个对象的引用”
return true;
if(!(o instanceof MyPoints))//使用instanceof操作符检查“参数是否是正确的类型”
return false;
MyPoints mypoints=(MyPoints)o;// 使用参数转换为正确的类型
return this.x==mypoints.getX()&&this.y==mypoints.getY();//对于该类中的每个“关键”域,检查参数中的域是否与该对象中对应的域相匹配
}
}
public class equalsTest{
public static void main(String[]args){
MyPoints point1=new MyPoints(1,2);
MyPoints point2=new MyPoints(2,3);
MyPoints point3=new MyPoints(1,2);
System.out.println("point1 equals point2 ? "+point1.equals(point2));
System.out.println("point2 equals point1 ? "+point2.equals(point1));
System.out.println("point1 equals point3 ? "+point1.equals(point3));
System.out.println("point3 equals point1 ? "+point3.equals(point1));
System.out.println("point1 equals point1 ? "+point1.equals(point1));
}
}
输出结果:
hashcode问题
将主方法改为:
public class equalsTest{
public static void main(String[]args){
MyPoints point1=new MyPoints(1,2);
MyPoints point2=new MyPoints(2,3);
MyPoints point3=new MyPoints(1,2);
System.out.println("point1 equals point2 ? "+point1.equals(point2));
System.out.println("point2 equals point1 ? "+point2.equals(point1));
System.out.println("point1 equals point3 ? "+point1.equals(point3));
System.out.println("point3 equals point1 ? "+point3.equals(point1));
System.out.println("point1 equals point1 ? "+point1.equals(point1));
Map<MyPoints, String> Mapabc
= new HashMap<MyPoints, String>();
Mapabc.put(point1, "point1");
System.out.println(Mapabc.get(new MyPoints(1,2)));
}
}
此时期待的输出结果是,point1
但是实际上却输出了null
原因:由于MyPoints类没有覆盖hashcode方法,导致了相等的实例对象具有不同的hashcode。
解决方法:覆盖MyPoints中的hashcode方法
在MyPoints中添加代码
@Override
public int hashCode() {
int result = hashCode;
if(result == 0) {
result = 17; //这个值是任意的
result = 31 * result + this.x; //31这个数字可以使用在jvm内部可以使用移位运算来代替减法来代替乘法。
result = 31 * result + this.y;
hashCode = result;
}
return result;
}
此时保证了equals方法相等的实例对象hashcode也是相同的。
结果截图: