为什么equals()方法要重写?
判断两个对象在逻辑上是否相等,如根据类的成员变量来判断两个类的实例是否相等,而继承Object中的equals方法只能判断两个引用变量是否是同一个对象。这样我们往往需要重写equals()方法。
我们向一个没有重复对象的集合中添加元素时,集合中存放的往往是对象,我们需要先判断集合中是否存在已知对象,这样就必须重写equals方法。
怎样重写equals()方法?
重写equals方法的要求:
1、自反性:对于任何非空引用x,x.equals(x)应该返回true。
2、对称性:对于任何引用x和y,如果x.equals(y)返回true,那么y.equals(x)也应该返回true。
3、传递性:对于任何引用x、y和z,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。
4、一致性:如果x和y引用的对象没有发生变化,那么反复调用x.equals(y)应该返回同样的结果。
5、非空性:对于任意非空引用x,x.equals(null)应该返回false。
1、自反性原则
在JavaBean中,经常会覆写equals方法,从而根据实际业务情况来判断两个对象是否相等,比如我们写一个person类,根据姓名来判断两个person类实例对象是否相等。代码如下:
1 public classPerson {2 privateString name;3
4 publicPerson(String name) {5 this.name =name;6 }7
8 publicString getName() {9 returnname;10 }11
12 public voidsetName(String name) {13 this.name =name;14 }15
16 @Override17 public booleanequals(Object obj) {18 if (obj instanceofPerson) {19 Person person =(Person) obj;20 returnname.equalsIgnoreCase(person.getName().trim());21 }22 return false;23 }24
25 public static voidmain(String[] args) {26 Person p1 = new Person("张三");27 Person p2 = new Person("张三 ");28 List list = new ArrayList();29 list.add(p1);30 list.add(p2);31 System.out.println("是否包含张三:" +list.contains(p1));32 System.out.println("是否包含张三:" +list.contains(p2));33 }34 }
list中含有这个生成的person对象,结果应该为true,但是实际结果:这里考虑了字符串空格的问题,去除前后的空格。
是否包含张三:true
是否包含张三:false
第二个为什么会是false呢?
原因在于list中检查是否含有元素时是通过调用对象的equals方法来判断的,也就是说 contains(p2)传递进去会依次执行p2.equals(p1)、p2.equals(p2),只要一个返回true,结果就是true。但是这里p2.equals(p2)返回的是false?由于我们对字符前后进行了空格的切割造成p2.equals(p2)的比较实际上是:“张三 ”.equals(“张三”),一个有空格,一个没有空格就出错了。
这个违背了equals的自反性原则:对于任何非空引用x,x.equals(x)应该返回true。
这里只要去掉trim方法就可以解决。
2、对称性原则
上面这个例子,还并不是很好,如果我们传入null值,会怎么样呢?增加一条语句:Person p2=new Person(null);
结果:
是否包含张三:trueException in thread"main" java.lang.NullPointerException//空指针异常
原因在执行p2.equals(p1)时,由于p2的name是一个null值,所以调用name.equalsIgnoreCase()方法时就会报空指针异常。
这是在覆写equals方法时没有遵循对称性原则:对于任何应用x,y的情形,如果想x.equals(y)返回true,那么y.equals(x),也应该返回true。
应该在equals方法里加上是否为null值的判断:
1 @Override2 public booleanequals(Object obj) {3 if (obj instanceofPerson) {4 Person person=(Person) obj;5 if (person.getName() == null || name == null) {6 return false;7 }else{8 returnname.equalsIgnoreCase(person.getName());9 }10 }11 return false;12 }
3、传递性原则
现在我们有一个Employee类继承自person类:
1 public class Employee extendsPerson{2 private intid;3
4
5 public int