打字猴:1.700442236e+09
1700442236
1700442237 System.out.println(e1.equals(e2));
1700442238
1700442239 }
1700442240
1700442241 上面定义了2个员工和1个社会闲杂人员,虽然他们同名同姓,但肯定不是同一个,输出应该都是false,那我们看看运行结果:
1700442242
1700442243 true
1700442244
1700442245 true
1700442246
1700442247 false
1700442248
1700442249 很不给力嘛,p1竟然等于e1,也等于e2,为什么不是同一个类的两个实例竟然也会相等呢?这很简单,因为p1.equals(e1)是调用父类Person的equals方法进行判断的,它使用instanceof关键字检查e1是否是Person的实例,由于两者存在继承关系,那结果当然是true了,相等也就没有任何问题了,但是反过来就不成立了,e1或e2可不等于p1,这也是违反对称性原则的一个典型案例。
1700442250
1700442251 更玄的是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。
1700442252
1700442253 这种情况发生的关键是父类使用了instanceof关键字,它是用来判断是否是一个类的实例对象的,这很容易让子类“钻空子”。想要解决也很简单,使用getClass来代替instanceof进行类型判断,Person类的equals方法修改后如下所示:
1700442254
1700442255 public boolean equals(Object obj){
1700442256
1700442257 if(obj!=null&&obj.getClass()==this.getClass()){
1700442258
1700442259 Person p=(Person)obj;
1700442260
1700442261 if(p.getName()==null||name==null){
1700442262
1700442263 return false;
1700442264
1700442265 }else{
1700442266
1700442267 return name.equalsIgnoreCase(p.getName());
1700442268
1700442269 }
1700442270
1700442271 }
1700442272
1700442273 return false;
1700442274
1700442275 }
1700442276
1700442277 当然,考虑到Employee也有可能被继承,也需要把它的instanceof修改为getClass。总之,在覆写equals时建议使用getClass进行类型判断,而不要使用instanceof。
1700442278
1700442279
1700442280
1700442281
1700442282 编写高质量代码:改善Java程序的151个建议 [:1700438117]
1700442283 编写高质量代码:改善Java程序的151个建议 建议48:覆写equals方法必须覆写hashCode方法
1700442284
1700442285 覆写equals方法必须覆写hashCode方法,这条规则基本上每个Javaer都知道,这也是JDK API上反复说明的,不过为什么要这样做呢?这两个方法之间有什么关系呢?本建议就来解释该问题,我们先来看如下代码:
[ 上一页 ]  [ :1.700442236e+09 ]  [ 下一页 ]