Java中的equals与==
本质区别
==
==
是用于比较对象在内存中的地址的。由于Java中的变量大多都是引用变量(也就是指针),所以只有当两个变量指向同一实例化的对象时,用==
才能返回true。
equals方法
equals方法则是通过该类中设计好的方法来判断两个比较的对象是否满足判等条件。例如String类中,设计的方法就是:比较每个字母,如果都一样就返回true。
对比
比如我们实例化了两个对象--->人,而且他们年龄和性别都一样。 但是他们在内存中的地址是不一样的。所以当使用==
判断时,返回的值是false。但是如果设计一个equals方法,表明如果年龄一样就返回true,那么通过equals方法返回的值就是true。因为在实际问题中对于判等的需求不同,设计方法也不同。(比如设计一个员工类,只要员工ID一样就可以返回true一样)。
equals方法的设计原则
满足等价关系
等价关系有三点要求:
1.==对称性==:若x.equals(y) 返回true, 那么 y.equals(x) 也应当返回true。
2.==自反性==:对于任何非空的x,x.equals(x) 应当恒返回true。
3.==传递性==: 若x.equals(y) 返回true, y.equals(z) 返回true,那么x.equals(z)也应当返回true。
也就是说,equals返回true的前提是建立在==类相同==,==对比目标相同==的情况下的。所以在设计的时候还要先检查类型是否相同
!
但是对于第一点:对称性,可能你会想到,有些情况下如果要对比父类和子类该怎么办?
如果严格按照等价关系来讲,只有类完全相同才能对比。如果x是父类,y是子类。在比较时,当y.equals(x)返回true时,x.equals(y)不一定成功(因为子类可以有父类的,但是对比时,父类不一定有子类的),这样不能满足==对称性==,所以理论上是不好的
但也可以结合实际问题变通
设想这样一个场景:
有一个公司,有很多Employee,也有Manager。Manager也是雇员,所以Manager当然也是Employee的子类了。在公司里,每个员工都有自己独特的ID,这就意味着我们可以直接通过ID来判断两个员工是不是同一个人了。不过这里就与上文的==对称性==产生了冲突。但是实际情况实际考虑,这里在设计的时候就可以设计成如果是继承关系的类,也可以比较
这里可以用到instanceof
关键词:
A instance of B
A是不是B的实例(A可以是B的子类或者同类)
当然,这种最好结合实际情况提前设计好呗。
代码
示列
以下是一个==严格遵循等价关系的==equals方法的写法:
public boolean equals(Object other)
{
//这只是个优化,如果都是一个地址了必定一样了。
if(this==other)
return true;
//检测是否为空,否则下一步会报错的
if(other==null)
return false;
//检测类型是否完全一样
if(getClass()!=other.getClass())
return false;
//如果你要想父类子类比较
//if(other instanceof this !=true)
// return false;
//确定了类型一样了,可以正式开始比较了
Employee employee = (Employee)otherObject;
//name是string类型,用String类型内已经写好了的euqals比较即可
//salary是int类型,是基本类型所以可以直接用==
return name.equals(other.name) && salary==other.salary
}
其他注意事项
覆盖
例如下面这一段代码,你能找的出问题吗(还是上面Manager和Employee的例子):
public class Manager
{
public boolean equals(Manager other)
{
return other!=null
&&this.bonus==other.bonus
&&getClass()==other.getClass()
}
//Manager特有的属性--奖金bonus(int类型),普通Employee是没有的
}
这个方法声明的显式参数类型是Manager,而我们刚才在Employee类里的equals方法里声明的是Object类的参数类型。所以说,这样写出来的只是个重载,并不是重写而已。所以为了避免错误类型的发生(比如编译器傻缺偏要用Employee那个不那么精确的比较方式),所以建议加上@Override标签。
hashCode方法
hashCode与equals的定义必须一致,如果x.equals(y)返回true,那么x.hashCode()与y.hashCode()也应当具有相同的值。所以在重写了equals方法之后,最好把你在equals中对比到的属性也在hashCode中散列了。