Java界的神器-使用Lombok来消除你的冗余代码量

简介

他是一个通过注解方式来减少你的POJO类的getter和setter等方法的一个工具,我这里演示的在Android Studio中的使用方式,当然如果你使用的是idea那么这方法也通用,如果你用的是eclipse,那么官网也有视频教程,我这里就不演示了

安装依赖

众所周知在在Android Studio中添加依赖有直接下载jar包和使用cradle的dependencies方法,我们这里直接使用dependencies方法

添加gradle依赖

在你的项目的build.grade文件中添加

1
provided 'org.projectlombok:lombok:1.12.6'

至于为什么是provided而不是compile,因为这个框架是在将java编译为class前处理代码了,意思是在生成的class文件中已经生成了getter和setter,所以这个依赖是我们在编译的时候使用,不需要打包到apk中

安装Lombok插件

虽然我们添加了依赖,但是Android Studio他知道怎么处理这个文件吗,肯定是不知道啦,所以我们的安装一个插件来告诉他怎么处理

Preferences > Plugins > Browse repositories

在输入框内输入combo,可看到已经搜索出来了这个插件,我们点击旁边的安装,安装完成后重启插件我们就安装完毕了,它的使用使用说明可以查看插件主页

现在插件虽然安装完了,但是Android Studio他怎么知道什么时候来使用这个插件呢,他是不是有个开关什么的,没错!你猜对了

开启项目的Annotation process

首先我们打开项目的设置,要强调的是项目的,而不是工具全局的设置,如下图

打开后按照下图勾选Enable annotation processing

配置文件 lombok.config

然后在Module根目录下新建一个lombok.config配置文件,加入两行配置

lombok.anyConstructor.suppressConstructorProperties = true
lombok.addGeneratedAnnotation = false

两个配置的作用是禁用掉一些在android上不存在的类,这些类在标准java中才存在。

到这里为止,工具和基本环境我们基本配置完了,接下来我们需要创建一个项目来测试

一些常用注解

@Getter and @Setter

可以很直观的从名字看出这个两个是分别用来生成Getter和Setter方法的

1
2
3
4
public class User {
@Getter @Setter private boolean employed = true;
@Setter(AccessLevel.PROTECTED) private String name;
}

相当于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class User {

private boolean employed = true;
private String name;

public User() {
}

public boolean isEmployed() {
return this.employed;
}

public void setEmployed(boolean employed) {
this.employed = employed;
}

protected void setName(String name) {
this.name = name;
}
}

到这里,大家肯定要问了,你说相当就等啊,或者上面相等的代码是怎么来的呢,其他我们可以直接反编译生成的class文件查看,打开Android Studio的class目录下的User.class文件,可以看到

同样下面的实例代码你可以这样查看,当然我们也可用通过Android Studio的

从上图我们发现我们没有在源代码写一些Getter方法,但是从Structure窗口看到这些方法已经自动生成了,是不是很神奇

@NonNull

提供一个参数的非空判断

1
2
@Getter @Setter @NonNull
private List<String> members;

等同于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@NonNull
private List<String> members;

@NonNull
public List<String> getMembers() {
return this.members;
}

public void setMembers(@NonNull List<String> members) {
if(members == null) {
throw new NullPointerException("members");
} else {
this.members = members;
}
}

@ToString

1
2
3
4
5
6
7
8
9
10
11
12
@ToString(exclude="name")
public class User {
@Getter
@Setter
private boolean employed = true;
@Setter(AccessLevel.PROTECTED)
private String name;
@Getter
@Setter
@NonNull
private List<String> members;
}

等同于

1
2
3
public String toString() {
return "User(employed=" + this.isEmployed() + ", members=" + this.getMembers() + ")";
}

@EqualsAndHashCode

1
2
3
4
5
6
7
8
9
10
11
12
@EqualsAndHashCode(exclude={"name"})
public class User {
@Getter
@Setter
private boolean employed = true;
@Setter(AccessLevel.PROTECTED)
private String name;
@Getter
@Setter
@NonNull
private List<String> members;
}

等同于

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
 public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if(!other.canEqual(this)) {
return false;
} else if(this.isEmployed() != other.isEmployed()) {
return false;
} else {
List this$members = this.getMembers();
List other$members = other.getMembers();
if(this$members == null) {
if(other$members != null) {
return false;
}
} else if(!this$members.equals(other$members)) {
return false;
}
return true;
}
}
}
public boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
boolean PRIME = true;
byte result = 1;
int result1 = result * 59 + (this.isEmployed()?79:97);
List $members = this.getMembers();
result1 = result1 * 59 + ($members == null?0:$members.hashCode());
return result1;
}

@Data

这个注解相当于同时使用@ToString, @EqualsAndHashCode, @Getter和@Setter

1
2
3
4
5
6
@Data
public class User {
private boolean employed = true;
private String name;
private List<String> members;
}

等同于

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
73
74
75
 public class User {
private boolean employed = true;
private String name;
private List<String> members;
public User() {
}
public boolean isEmployed() {
return this.employed;
}
public String getName() {
return this.name;
}
public List<String> getMembers() {
return this.members;
}
public void setEmployed(boolean employed) {
this.employed = employed;
}
public void setName(String name) {
this.name = name;
}
public void setMembers(List<String> members) {
this.members = members;
}
public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if(!other.canEqual(this)) {
return false;
} else if(this.isEmployed() != other.isEmployed()) {
return false;
} else {
String this$name = this.getName();
String other$name = other.getName();
if(this$name == null) {
if(other$name != null) {
return false;
}
} else if(!this$name.equals(other$name)) {
return false;
}
List this$members = this.getMembers();
List other$members = other.getMembers();
if(this$members == null) {
if(other$members != null) {
return false;
}
} else if(!this$members.equals(other$members)) {
return false;
}
return true;
}
}
}
public boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
boolean PRIME = true;
byte result = 1;
int result1 = result * 59 + (this.isEmployed()?79:97);
String $name = this.getName();
result1 = result1 * 59 + ($name == null?0:$name.hashCode());
List $members = this.getMembers();
result1 = result1 * 59 + ($members == null?0:$members.hashCode());
return result1;
}
public String toString() {
return "User(employed=" + this.isEmployed() + ", name=" + this.getName() + ", members=" + this.getMembers() + ")";
}
}

@Cleanup

他可以帮我们在需要释放的资源位置自动加上释放代码

1
2
3
4
5
6
7
8
9
 public void testCleanUp() {
try {
@Cleanup ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(new byte[] {'Y','e','s'});
System.out.println(baos.toString());
} catch (IOException e) {
e.printStackTrace();
}
}

等同于

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 public void testCleanUp() {
try {
ByteArrayOutputStream e = new ByteArrayOutputStream();
try {
e.write(new byte[]{(byte)89, (byte)101, (byte)115});
System.out.println(e.toString());
} finally {
if(Collections.singletonList(e).get(0) != null) {
e.close();
}
}
} catch (IOException var6) {
var6.printStackTrace();
}
}

@Synchronized

可以帮我们在方法上添加同步代码块

1
2
3
4
5
6
7
 public class TestSync {
private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");
@Synchronized
public String synchronizedFormat(Date date) {
return format.format(date);
}
}

等同于

1
2
3
4
5
6
7
8
9
10
11
12
 public class TestSync {
private final Object $lock = new Object[0];
private DateFormat format = new SimpleDateFormat("MM-dd-YYYY");
public TestSync() {
}
public String synchronizedFormat(Date date) {
Object var2 = this.$lock;
synchronized(this.$lock) {
return this.format.format(date);
}
}
}

基本的使用就介绍到这里,下面一份完整代码
User.java

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
package com.woblog.testlombok;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import lombok.AccessLevel;
import lombok.Cleanup;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NonNull;
import lombok.Setter;
import lombok.SneakyThrows;
import lombok.Synchronized;
import lombok.ToString;
/**
* Created by renpingqing on 16/6/18.
*/
@Data
@ToString(callSuper = true)
/**
* 这里如果不写false,会报错,
* Error:(21, 1) 警告: Generating equals/hashCode implementation but without a call to superclass,
* even though this class does not extend java.lang.Object. If this is intentional,
* add '@EqualsAndHashCode(callSuper=false)' to your type.
*/
@EqualsAndHashCode(callSuper = false)
public class User extends BasePOJO {
private final Object lockObj = new Object();
/**
* userid只生成getUserId
*/
private
@Getter
String userId;
private String username;
private int gender;
private float price;
@Setter(AccessLevel.PROTECTED)
private boolean vip = false; //vip,或者isVip都会生成isVip
private List<String> members;
/**
* name不能为空
*
* @param name
* @return
*/
private String sayHello(@NonNull String name) {
return String.format("hi %s", name);
}
@SneakyThrows(IOException.class)
public void closeabale() {
@Cleanup InputStream is = new ByteArrayInputStream("hello world".getBytes());
System.out.println(is.available());
}
@Synchronized("lockObj")
public void lockMethod() {
System.out.println("test lock method");
}
}

他生成的代码如下:

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.woblog.testlombok;
import com.woblog.testlombok.BasePOJO;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import lombok.NonNull;
public class User extends BasePOJO {
private final Object lockObj = new Object();
private String userId;
private String username;
private int gender;
private float price;
private boolean vip = false;
private List<String> members;
private String sayHello(@NonNull String name) {
if(name == null) {
throw new NullPointerException("name");
} else {
return String.format("hi %s", new Object[]{name});
}
}
public void closeabale() {
try {
ByteArrayInputStream $ex = new ByteArrayInputStream("hello world".getBytes());
try {
System.out.println($ex.available());
} finally {
if(Collections.singletonList($ex).get(0) != null) {
$ex.close();
}
}
} catch (IOException var6) {
throw var6;
}
}
public void lockMethod() {
Object var1 = this.lockObj;
synchronized(this.lockObj) {
System.out.println("test lock method");
}
}
public User() {
}
public Object getLockObj() {
return this.lockObj;
}
public String getUsername() {
return this.username;
}
public int getGender() {
return this.gender;
}
public float getPrice() {
return this.price;
}
public boolean isVip() {
return this.vip;
}
public List<String> getMembers() {
return this.members;
}
public void setUserId(String userId) {
this.userId = userId;
}
public void setUsername(String username) {
this.username = username;
}
public void setGender(int gender) {
this.gender = gender;
}
public void setPrice(float price) {
this.price = price;
}
public void setMembers(List<String> members) {
this.members = members;
}
public String toString() {
return "User(super=" + super.toString() + ", lockObj=" + this.getLockObj() + ", userId=" + this.getUserId() + ", username=" + this.getUsername() + ", gender=" + this.getGender() + ", price=" + this.getPrice() + ", vip=" + this.isVip() + ", members=" + this.getMembers() + ")";
}
public boolean equals(Object o) {
if(o == this) {
return true;
} else if(!(o instanceof User)) {
return false;
} else {
User other = (User)o;
if(!other.canEqual(this)) {
return false;
} else {
label71: {
Object this$lockObj = this.getLockObj();
Object other$lockObj = other.getLockObj();
if(this$lockObj == null) {
if(other$lockObj == null) {
break label71;
}
} else if(this$lockObj.equals(other$lockObj)) {
break label71;
}
return false;
}
String this$userId = this.getUserId();
String other$userId = other.getUserId();
if(this$userId == null) {
if(other$userId != null) {
return false;
}
} else if(!this$userId.equals(other$userId)) {
return false;
}
label57: {
String this$username = this.getUsername();
String other$username = other.getUsername();
if(this$username == null) {
if(other$username == null) {
break label57;
}
} else if(this$username.equals(other$username)) {
break label57;
}
return false;
}
if(this.getGender() != other.getGender()) {
return false;
} else if(Float.compare(this.getPrice(), other.getPrice()) != 0) {
return false;
} else if(this.isVip() != other.isVip()) {
return false;
} else {
List this$members = this.getMembers();
List other$members = other.getMembers();
if(this$members == null) {
if(other$members != null) {
return false;
}
} else if(!this$members.equals(other$members)) {
return false;
}
return true;
}
}
}
}
public boolean canEqual(Object other) {
return other instanceof User;
}
public int hashCode() {
boolean PRIME = true;
byte result = 1;
Object $lockObj = this.getLockObj();
int result1 = result * 59 + ($lockObj == null?0:$lockObj.hashCode());
String $userId = this.getUserId();
result1 = result1 * 59 + ($userId == null?0:$userId.hashCode());
String $username = this.getUsername();
result1 = result1 * 59 + ($username == null?0:$username.hashCode());
result1 = result1 * 59 + this.getGender();
result1 = result1 * 59 + Float.floatToIntBits(this.getPrice());
result1 = result1 * 59 + (this.isVip()?79:97);
List $members = this.getMembers();
result1 = result1 * 59 + ($members == null?0:$members.hashCode());
return result1;
}
public String getUserId() {
return this.userId;
}
protected void setVip(boolean vip) {
this.vip = vip;
}
}

可以看到代码量差不多缩减了三倍,但是他也有一些缺点,比如:

大大降低了源代码文件的可读性和完整性,降低了阅读源代码的舒适度。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2021 朝着牛逼的道路一路狂奔 All Rights Reserved.

访客数 : | 访问量 :