java getclass 相等_[改善Java代码]在equals中使用getClass进行类型判断

建议47: 在equals中使用getClass进行类型判断

本节我们继续讨论覆写equals的问题。这次我们编写一个员工Employee类继承Person类,这很正常,员工也是人嘛,而且在JEE中JavaBean有继承关系也很常见,代码如下:

1 public classClient {2 public static voidmain(String[] args) {3 Employee e1 = new Employee("张三",100);4 Employee e2 = new Employee("张三",1001);5 Person p1 = new Person("张三");6 System.out.println(p1.equals(e1));7 System.out.println(p1.equals(e2));8 System.out.println(e1.equals(e2));9 }10 }11

12 classPerson{13 privateString name;14

15 publicPerson(String _name){16 name =_name;17 }18

19 @Override20 public booleanequals(Object obj) {21 if(obj instanceofPerson){22 Person p =(Person) obj;23 returnname.equalsIgnoreCase(p.getName().trim());24 }25 return false;26 }27

28 publicString getName() {29 returnname;30 }31

32 public voidsetName(String name) {33 this.name =name;34 }35 }36

37 class Employee extendsPerson{38 private intid;39 /*id的getter/setter方法省略*/

40 public Employee(String _name,int_id) {41 super(_name);42 id =_id;43 }44

45 public intgetId() {46 returnid;47 }48

49 public void setId(intid) {50 this.id =id;51 }52

53 @Override54 public booleanequals(Object obj) {55 if(obj instanceofEmployee){56 Employee e =(Employee) obj;57 return super.equals(obj)&& e.getId() ==id;58 }59 return false;60 }61 }

输出结果:

true

true

false

很不给力嘛,p1竟然等于e1,也等于e2,为什么不是同一个类的两个实例竟然也会相等呢?这很简单,因为p1.equals(e1) 是调用父类Person的equals方法进行判断的,它使用instanceof关键字检查e1是否是Person的实例,由于两者存在继承关系,那结果当然是true了,相等也就没有任何问题了,但是反过来就不成立了,e1或e2可不等于p1,这也是违反对称性原则的一个典型案例。

更玄的是p1与e1、e2相等,但e1竟然与e2不相等,似乎一个简单的等号传递都不能实现。这才是我们要分析的真正重点:e1.equals(e2)调用的是子类Employee的equals方法,不仅仅要判断姓名相同,还要判断工号是否相同,两者工号是不同的,不相等也是自然的了。等式不传递是因为违反了equals的传递性原则,传递性原则是指对于实例对象x、y、z来说,如果x.equals(y)返回true,y.equals(z)返回true,那么x.equals(z)也应该返回true。

这种情况发生的关键是父类使用了instanceof关键字,它是用来判断是否是一个类的实例对象的,这很容易让子类“钻空子”。想要解决也很简单,使用getClass来代替instanceof进行类型判断,Person类的equals方法修改后如下所示:

1 public booleanequals(Object obj) {2 if(obj!=null && obj.getClass() == this.getClass()){3 Person p =(Person) obj;4 if(p.getName()==null || name==null){5 return false;6 }else{7 returnname.equalsIgnoreCase(p.getName());8 }9 }10 return false;11 }

当然,考虑到Employee也有可能被继承,也需要把它的instanceof修改为getClass。总之,在覆写equals时建议使用getClass进行类型判断,而不要使用instanceof。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值