我们在平常开发中,最令我们心烦的事情,就是 Bean 类的 Get 和 Set 方法了,虽然 Studio 上面有自动帮我们生成 Get 和 Set 的工具,但是这种方式其实也有弊端,那就是我们在 Review Bean 类代码的时候,特别是有内部类的情况下,这些 Get 和 Set 方法其实给我们造成了一些 Review 障碍,其实这些 Get 和 Set 方法没有什么营养,经过自动生成后基本不会再管了。
那我们有没有一种更好的方式来做这件事?答案当然是有的,接下来让我们直接进入主题。
为了更好的理解新旧写法之间的差异,这里列举了两种关于写法进行比较
写法一
public class UserBean {
private DataBean data;
private CookieBean cookie;
private int newUser;
private int smsStatus;
private boolean isTest;
private String unionid;
private String openid;
public String getUnionid() {
return unionid;
}
public void setUnionid(String unionid) {
this.unionid = unionid;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public DataBean getData() {
return data;
}
public void setData(DataBean data) {
this.data = data;
}
public CookieBean getCookie() {
return cookie;
}
public void setCookie(CookieBean cookie) {
this.cookie = cookie;
}
public int getNewUser() {
return newUser;
}
public void setNewUser(int newUser) {
this.newUser = newUser;
}
public int getSmsStatus() {
return smsStatus;
}
public void setSmsStatus(int smsStatus) {
this.smsStatus = smsStatus;
}
public boolean isTest() {
return isTest;
}
public void setTest(boolean test) {
isTest = test;
}
public static class DataBean {
private String id;
private String name;
private String nickname;
private int sex;
private String mobile;
private int mobile_bind;
private String score;
private String parentName;
private String relation;
private String birthday;
private String avatarPath;
private int attendClass;
private int is_new_user;
public int getMobile_bind() {
return mobile_bind;
}
public void setMobile_bind(int mobile_bind) {
this.mobile_bind = mobile_bind;
}
public int getIs_new_user() {
return is_new_user;
}
public void setIs_new_user(int is_new_user) {
this.is_new_user = is_new_user;
}
public int getAttendClass() {
return attendClass;
}
public void setAttendClass(int attendClass) {
this.attendClass = attendClass;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getScore() {
return score;
}
public void setScore(String score) {
this.score = score;
}
public String getParentName() {
return parentName;
}
public void setParentName(String parentName) {
this.parentName = parentName;
}
public String getRelation() {
return relation;
}
public void setRelation(String relation) {
this.relation = relation;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
public String getAvatarPath() {
return avatarPath;
}
public void setAvatarPath(String avatarPath) {
this.avatarPath = avatarPath;
}
}
public static class CookieBean {
private String uid;
private String time;
private String token;
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
}
写法二
@Setter@Getter
public class UserBean {
private DataBean data;
private CookieBean cookie;
private int newUser;
private int smsStatus;
private boolean isTest;
private String unionid;
private String openid;
@Setter
@Getter
public static class DataBean {
private String id;
private String name;
private String nickname;
private int sex;
private String mobile;
private int mobile_bind;
private String score;
private String parentName;
private String relation;
private String birthday;
private String avatarPath;
private int attendClass;
private int is_new_user;
}
@Setter
@Getter
public static class CookieBean {
private String uid;
private String time;
private String token;
}
}
写法 PK
经过比较,第一种写法代码行数有 218 行,而第二种写法代码行数仅有 40 行代码,很明显第二种写法清爽了许多。
假设是你,会选择哪一种?如果是我,会毫不犹豫选择第二种。一个注解居然可以少写很多代码,性价比真的很高。
这个时候你可能会有些疑问,这个到底是怎么实现的?会不会影响性能?有没有什么缺点?
带着这些疑问让我们开始讲今天的主角:lombok,先讲讲如何集成和使用
集成使用
在 Gradle 中添加依赖
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.12'
annotationProcessor 'org.projectlombok:lombok:1.18.12'
}
你以为到这里就结束了?其实不然,这个功能还需要插件的支持
安装成功之后提示重启,我们选择重启即可
注解解释
@Getter:为这个类的字段自动生成 Get 方法
@Setter:为这个类的字段自动生成 Set 方法
@ToString:为这个类自动生成 toString 方法
@NoArgsConstructor:为这个类自动生成一个空参构造函数
@AllArgsConstructor:根据这个类的字段自动生成一个全参构造函数
@RequiredArgsConstructor:为这个类自动生成特定的构造函数,构造函数中的参数是被 final 修饰又或者 @NonNull 约束的字段
@EqualsAndHashCode:根据这个类的字段自动生成 equals 和 hashCode 方法,需要注意的是 hashCode 是通过字段的值计算得来的
@Data:相当于同时使用了 @Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstrutor
原理
Lombok 有点类似于 APT,但其实它并不是 APT,因为 APT 无法修改类的内容,只能通过生成辅助类来完成。也有点类似于 AOP,但是 AOP 只针对方法进行切面,而 Lombok 是在编译时通过修改 class 文件生成的内容,也就是在 java 转换成 class 之前做修改,所以基于这一实现原理,Lombok 对性能没有任何影响。
Lombok本质上就是一个实现了
JSR 269 API
的程序。在使用 javac 的过程中,它产生作用的具体流程如下:javac 对源代码进行分析,生成了一棵抽象语法树(AST)
运行过程中调用实现了
JSR 269 API
的 Lombok 程序此时 Lombok 就对第一步骤得到的 AST 进行处理,找到注解所在类对应的语法树(AST),然后修改该语法树(AST),增加注解所定义的相应树节点
javac 使用修改后的抽象语法树(AST)生成字节码文件,即给 class 增加新的节点(代码块)
优缺点
优点
相比传统手写,这种方式更加快捷
相比自动生成,这种方式更加简洁
缺点
如果是团队开发,需要每一个项目成员安装此插件,否则无法编译通过
作者:Android轮子哥
链接:https://www.jianshu.com/p/f1f888e4a35f
喜欢 就关注吧,欢迎投稿!
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/自从学了这招,再也没有写过get和set方法了/