java~lombok的@Data引发的问题
我们问题lombok是可以精简我们的代码的,让开发人员把精力放在业务上,而它封装的注解我们在使用时,需要多注意一下;@Data注解它是一个混合注释,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode
的功能,而我们问题@EqualsAndHashCode是重写equals和hash的注释,如果你是一个类,那可以不关心它;而如果你的类中有继承(父类子类),那么就要注意一下了。
危险的@Data
子类不能完全代表父类
@EqualsAndHashCode注解里有个字段callSuper,它的默认值是false,意思是在重写时,不会将父类的字段写到equals里;而@Data这个注解由于包含了@EqualsAndHashCode,所以它也有这个特性,即子类强制实现了重写equals和hashCode,并且只重写了自己的属性,这时,问题就来了,当两个对象比较时,如果子类属性相同而父类属性不同,结果也为true,这是非常严重的bug。
定义两种类,基类People,和两个子类Man和Woman
@Data
class Person {
String name;
}
@Data
//重写时带上父类字段
@EqualsAndHashCode(callSuper = true)
class Man extends Person {
Boolean hunting;
}
@Data
//重写equals时不会带上父类的字段,同种类型比较时,当子类字段相同时,结果就为true,这显然是不准确的.
@EqualsAndHashCode(callSuper = false)
class Woman extends Person {
Boolean spin;
}
测试的结果,我们是可以猜出来的,父类里的字段不相同时,结果应该为false,但如果 @EqualsAndHashCode(callSuper = false)
,结果竟然是true,这也是正常的,因为它并没有重写父类的属性name,所以只要子类字段相同,结果就认为相同了。
@Test
public void supperSubEqual() {
Man man = new Man();
man.setName("zzl");
man.setHunting(true);
Man man1 = new Man();
man1.setHunting(true);
man1.setName("lind");
log.info("man==man1 ? {}", man.equals(man1)); // false
Woman woman = new Woman();
woman.setName("zzl");
woman.setSpin(true);
Woman woman1 = new Woman();
woman1.setSpin(true);
woman1.setName("lind");
log.info("woman==woman1 ? {}", woman.equals(woman1)); // true
}
总结
在使用@Data时,我们尽量把 @EqualsAndHashCode(callSuper = true)加上,因为你不加,它相当于是false;或者杜绝使用@Data,而用@Getter,@Setter,@ToString代替它。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
2017-09-07 爱上MVC~业务层刻意抛出异常,全局异常的捕获它并按格式返回
2015-09-07 基础才是重中之重~再说面向接口的编程