@Data取代Get,Set方法的使用总结以及注意事项
前言:
开发过程中发现前辈的代码中实体类没有任何get,set方法但是却能正常使用get,set方法,仔细研究发现每个实体类中都使用了@Data 注解于是仔细研究了下@Data的使用方法。
介绍:
@Data 注解的主要作用是提高代码的简洁,使用这个注解可以省去代码中大量的get()、 set()、 toString()等方法;
使用:
要使用 @Data 注解要先引入lombok工具类库,可以用简单的注解形式来简化代码,提高开发效率。
在maven中添加依赖
1
2
3
4
5
6
7<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.4</version> <scope>provided</scope> </dependency>
注意!
在编译器中添加插件
这里以IDEA为例,在setting的plugin里搜索lombok plugin,安装插件。重启即可。
接下来就是写实体类的时候就可以直接使用这个标签了!
例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14@Data public class UsersDto { @Id private Integer id; private String name; private String password; /** * 性别 0男生 1女生 */ private Byte sex; private String email; private String city; }
常用的几个注解:
@Data : 注在类上,提供类的get、set、equals、hashCode、canEqual、toString方法
@AllArgsConstructor : 注在类上,提供类的全参构造
@NoArgsConstructor : 注在类上,提供类的无参构造
@Setter : 注在属性上,提供 set 方法
@Getter : 注在属性上,提供 get 方法
@EqualsAndHashCode : 注在类上,提供对应的 equals 和 hashCode 方法
@Log4j/@Slf4j : 注在类上,提供对应的 Logger 对象,变量名为 log
这样使用是不是很方便?
但是!
多年的经验告诉我,有失就有得,为什么这么好用的标签没有大面积使用呢?于是乎我深入研究了一下这个标签的使用,发现原来@Data标签还有这么多的注意事项,如果没注意的话,项目很可能出现难以预料的bug而且排查起来也很困难,下面举例说明,也顺便警醒自己和看到这篇文章的大家,如果遇到新的工具,没研究透之前,千万别贸然使用到项目中。
@Data注解它是一个混合注释,它包含了@Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode的功能,而我们问题@EqualsAndHashCode是重写equals和hash的注释,如果你是一个类,那可以不关心它;而如果你的类中有继承(父类子类),那么就要注意一下了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73package com.*.user; import lombok.Data; import lombok.EqualsAndHashCode; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.Objects; //@RunWith(SpringRunner.class) //@SpringBootTest public class LombokTest { @Data class Person { String name; int age; } @Data //重写时带上父类字段 @EqualsAndHashCode(callSuper = true) class Man extends Person { Boolean hunting; } @Data //重写equals时不会带上父类的字段,同种类型比较时,当子类字段相同时,结果就为true,这显然是不准确的. @EqualsAndHashCode(callSuper = false) class Woman extends Person { Boolean spin; } @Test public void tsetlombok() { Man t1 = new Man(); Man t2 = new Man(); t1.setName("123"); t2.setName("12345"); String name = "1"; t1.name = name; t2.name = name; int age = 1; t1.age = age; t2.age = age; System.out.println(t1.equals(t2));//true System.out.println(t2.equals(t1));//true System.out.println(t1.hashCode());//376050 System.out.println(t2.hashCode());//376050 System.out.println(t1 == t2);//false System.out.println(Objects.equals(t1, t2));//true } @Test public void supperSubEqual() { Man man = new Man(); man.setName("小张"); man.setAge(22); man.setHunting(true); Man man1 = new Man(); man1.setHunting(true); man1.setName("小李"); man.setAge(23); System.out.println("man==man1?"+ man.equals(man1)); // false Woman woman = new Woman(); woman.setName("小赵"); man.setAge(19); woman.setSpin(true); Woman woman1 = new Woman(); woman1.setSpin(true); man.setAge(18); woman1.setName("小美"); System.out.println("woman==woman1? "+ woman.equals(woman1)); // true } }
@EqualsAndHashCode注解里有个字段callSuper,它的默认值是false,意思是在重写时,不会将父类的字段写到equals里;而@Data这个注解由于包含了@EqualsAndHashCode,所以它也有这个特性,即子类强制实现了重写equals和hashCode,并且只重写了自己的属性,这时,问题就来了,当两个对象比较时,如果子类属性相同而父类属性不同,结果也为true,这是非常严重的bug。
通过以上两个test我们发现:
父类里的字段不相同时,结果应该为false,但如果 @EqualsAndHashCode(callSuper = false),结果竟然是true,这是因为它并没有重写父类的属性name,所以只要子类字段相同,结果就认为相同了。
所以在使用@Data时,我们尽量把 @EqualsAndHashCode(callSuper = true)加上,因为你不加,它相当于是false;
优点:
1、能通过注解的形式自动生成构造器、getter/setter、equals、hashcode、toString等方法,提高了一定的开发效率
2、让代码变得简洁,不用过多的去关注相应的方法
3、属性做修改时,也简化了维护为这些属性所生成的getter/setter方法等
缺点:
1、不支持多种参数构造器的重载
2、虽然省去了手动创建getter/setter方法的麻烦,但大大降低了源代码的可读性和完整性
总结:
1、用了@Data就不要有继承关系
2、自己重写equals(), Lombok 不会对显式重写的方法进行生成。
3、显式使用@EqualsAndHashCode(callSuper = true), Lombok 会以显式指定的为准。
4、或者杜绝使用@Data,而用@Getter,@Setter,@ToString代替它。
lombok 只是省去了一些人工生成代码的麻烦,但是这些getter/setter等等的方法,用IDE的快捷键也可很方便的生成。况且,有时通过给getter/setter加一点点业务代码(但通常不建议这么加),能极大的简化某些业务场景的代码。
用还是不用,这中间如何取舍,自然是要看项目的需要,灵活运用。
最后
以上就是傲娇柜子最近收集整理的关于@Data取代Get,Set方法的使用总结以及注意事项@Data取代Get,Set方法的使用总结以及注意事项的全部内容,更多相关@Data取代Get,Set方法内容请搜索靠谱客的其他文章。
发表评论 取消回复