我們在平常開發(fā)中查剖,最令我們心煩的事情钾虐,就是 Bean 類的 Get 和 Set 方法了,雖然 Studio 上面有自動幫我們生成 Get 和 Set 的工具笋庄,但是這種方式其實也有弊端效扫,那就是我們在 Review Bean 類代碼的時候,特別是有內(nèi)部類的情況下直砂,這些 Get 和 Set 方法其實給我們造成了一些 Review 障礙菌仁,其實這些 Get 和 Set 方法沒有什么營養(yǎng),經(jīng)過自動生成后基本不會再管了静暂。
那我們有沒有一種更好的方式來做這件事济丘?答案當(dāng)然是有的,接下來讓我們直接進入主題洽蛀。
為了更好的理解新舊寫法之間的差異摹迷,這里列舉了兩種關(guān)于寫法進行比較
寫法一
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
經(jīng)過比較,第一種寫法代碼行數(shù)有 218 行郊供,而第二種寫法代碼行數(shù)僅有 40 行代碼峡碉,很明顯第二種寫法清爽了許多。
假設(shè)是你驮审,會選擇哪一種鲫寄?如果是我,會毫不猶豫選擇第二種头岔。一個注解居然可以少寫很多代碼塔拳,性價比真的很高鼠证。
這個時候你可能會有些疑問峡竣,這個到底是怎么實現(xiàn)的?會不會影響性能量九?有沒有什么缺點适掰?
帶著這些疑問讓我們開始講今天的主角:lombok颂碧,先講講如何集成和使用
集成使用
在 Gradle 中添加依賴
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.12'
annotationProcessor 'org.projectlombok:lombok:1.18.12'
}
你以為到這里就結(jié)束了?其實不然类浪,這個功能還需要插件的支持
安裝成功之后提示重啟载城,我們選擇重啟即可
注解解釋
@Getter:為這個類的字段自動生成 Get 方法
@Setter:為這個類的字段自動生成 Set 方法
@ToString:為這個類自動生成 toString 方法
@NoArgsConstructor:為這個類自動生成一個空參構(gòu)造函數(shù)
@AllArgsConstructor:根據(jù)這個類的字段自動生成一個全參構(gòu)造函數(shù)
@RequiredArgsConstructor:為這個類自動生成特定的構(gòu)造函數(shù),構(gòu)造函數(shù)中的參數(shù)是被 final 修飾又或者 @NonNull 約束的字段
@EqualsAndHashCode:根據(jù)這個類的字段自動生成 equals 和 hashCode 方法费就,需要注意的是 hashCode 是通過字段的值計算得來的
@Data:相當(dāng)于同時使用了 @Getter诉瓦、@Setter、@ToString力细、@EqualsAndHashCode睬澡、@RequiredArgsConstrutor
原理
Lombok 有點類似于 APT,但其實它并不是 APT眠蚂,因為 APT 無法修改類的內(nèi)容煞聪,只能通過生成輔助類來完成。也有點類似于 AOP逝慧,但是 AOP 只針對方法進行切面昔脯,而 Lombok 是在編譯時通過修改 class 文件生成的內(nèi)容,也就是在 java 轉(zhuǎn)換成 class 之前做修改笛臣,所以基于這一實現(xiàn)原理云稚,Lombok 對性能沒有任何影響。
-
Lombok本質(zhì)上就是一個實現(xiàn)了
JSR 269 API
的程序沈堡。在使用 javac 的過程中碱鳞,它產(chǎn)生作用的具體流程如下:javac 對源代碼進行分析,生成了一棵抽象語法樹(AST)
運行過程中調(diào)用實現(xiàn)了
JSR 269 API
的 Lombok 程序此時 Lombok 就對第一步驟得到的 AST 進行處理踱蛀,找到注解所在類對應(yīng)的語法樹(AST)窿给,然后修改該語法樹(AST),增加注解所定義的相應(yīng)樹節(jié)點
javac 使用修改后的抽象語法樹(AST)生成字節(jié)碼文件率拒,即給 class 增加新的節(jié)點(代碼塊)
優(yōu)缺點
-
優(yōu)點
相比傳統(tǒng)手寫崩泡,這種方式更加快捷
相比自動生成,這種方式更加簡潔
-
缺點
- 如果是團隊開發(fā)猬膨,需要每一個項目成員安裝此插件角撞,否則無法編譯通過