轉(zhuǎn)載請(qǐng)注明出處:http://tedyin.me/2016/04/11/auto-value/
在Java中通常定義一個(gè)模型類時(shí),需要定義一堆不同類型的成員變量,而且為了滿足面向?qū)ο蟮幕咎卣?,又要定義一堆相應(yīng)的Getter和Setter等方法,這個(gè)過程是非??菰锏囊獙懸欢褬影宕a。雖然現(xiàn)在 IDE 可以很好的幫我們生成這些樣板代碼,但是如果看到一個(gè)模型類里面有這么一堆的方法,總覺是會(huì)覺得不夠清晰。
我只想知道這個(gè)模型有哪些屬性,以及特殊的方法,并不想知道大家都有的東西,你卻非要讓我看。。。
好了,現(xiàn)在有辦法可以解決這個(gè)問題了,使用 Google 開源的 AutoValue 就可以解決上述煩惱,而且最近AutoValue項(xiàng)目支持了大家期待已久的Extension API,使得AutoValue更加靈活,至于這個(gè)Extension API是干啥的后面會(huì)講到,現(xiàn)在暫時(shí)不用去關(guān)心他。
普通的 Java 模型
我們這里舉個(gè)故事(Story)的例子,一個(gè)故事模型擁有一個(gè)id,以及一個(gè)title。下面我們來看下用Java代碼來表示該模型的寫法。
不太嚴(yán)謹(jǐn)?shù)膶懛?/h3>
我們先來看下一般情況下我們是怎么定義這個(gè) POJO 的業(yè)務(wù)模型的。
public class Story{
public int id;
public String title;
}
上面的寫法非常簡(jiǎn)單,不過有些情況下可能會(huì)有問題,比如對(duì)象比較時(shí),而且也不符合封裝的要求,不過一般情況下業(yè)務(wù)邏輯簡(jiǎn)單,還處在快速迭代的時(shí)候這樣寫也沒什么問題,而且重點(diǎn)是他 只有4行代碼!
比較規(guī)范的寫法
下面看下正常情況下的寫法:
public class Story{
private int id;
private String title;
public Story(int id, String title){
this.id = id;
this.title = title;
}
public int id(){
return this.id;
}
public int title(){
return this.title;
}
}
這樣寫符合了面向?qū)ο蟮幕咎卣?code>封裝的要求,但是如果這個(gè)Story是在列表或者集合中有用到比較的時(shí)候,這么寫是有問題的,應(yīng)該繼續(xù)覆蓋hashCode()和equals()方法,如果有特殊格式的輸出,還得覆蓋toString()方法。
把這些東西都補(bǔ)全的寫法如下:
public class Story{
private int id;
private String title;
public Story(int id, String title){
this.id = id;
this.title = title;
}
public int id(){
return this.id;
}
public int title(){
return this.title;
}
@Override
public String toString(){
return id + title;
}
@Override
public int hashCode() {
int hash = 7;
hash = 31 * hash + this.id;
hash = 31 * hash + (null == title ? 0 : title.hashCode());
return hash;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Stroy)) return false;
Story s = (Story) o;
if (s.id != s.id) return false;
return s.title.equals(s.title);
}
}
上面的版本是一個(gè)比較完整的模型寫法,相比起最初的版本,代碼多了不少?gòu)脑瓉淼?code>4行變成了現(xiàn)在的39行!
OMG!現(xiàn)在的版本還沒有實(shí)現(xiàn)Parcelable接口,如果再在他的基礎(chǔ)上實(shí)現(xiàn)Parcelable接口,那代碼又得增加十幾行,想想都心累啊。
使用AutoValue拯救你的代碼
我本想要一個(gè)只有幾行的模型類,但是出于各方面原因,我得到了一個(gè)幾十行代碼的模型類,為了解決這個(gè)問題偉大的Google開發(fā)了AutoValue這個(gè)庫來自動(dòng)生成這些樣板代碼,解放我們的雙手,讓我們把更多的精力放在更重要的事情上。
使用AutoValue
使用方法很簡(jiǎn)單,只需要在你的項(xiàng)目中引入AutoValue的插件即可
dependencies {
apt 'com.google.auto.value:auto-value:1.2'
}
然后在代碼中使用@AutoValue注解來指定哪個(gè)類需要生成類似于上面的樣板代碼。下面我們使用AutoValue來重新實(shí)現(xiàn)一下Story模型。
@AutoValue
public abstract class Story{
public abstract int id();
public abstract String title();
}
使用@AutoValue注解后,AutoValue會(huì)生成一個(gè)AutoValue_你的類名為名稱的類,這個(gè)類是包級(jí)私有的,他里面有私有的成員變量,對(duì)應(yīng)的構(gòu)造函數(shù),以及重寫的hashCode()、equals()和toString()方法,而且這些方法都是被測(cè)試過的確保無誤的,你可以放心的使用。由于這個(gè)生成的子類是包級(jí)私有的,所以這里在給Story提供構(gòu)造方法的時(shí)候需要提供一個(gè)靜態(tài)的構(gòu)造方法,代碼如下:
@AutoValue
public abstract class Story{
public abstract int id();
public abstract String title();
public static Story create(int id, String title){
new AutoValue_Story(id,title);
}
}
好了,使用AutoValue后,這短短幾行代碼就完成了上面幾十行代碼干的事,而且這樣生成出來的代碼都是被測(cè)試過準(zhǔn)確無誤的,這也避免了一些因?yàn)槭终`或者邏輯錯(cuò)誤導(dǎo)致的BUG的產(chǎn)生,是不是很爽?必須很爽?。?/p>
But... 我們要更爽一點(diǎn)!
AutoValue Extension API
大家注意到?jīng)]有上面使用AutoValue實(shí)現(xiàn)的Story模型并沒有實(shí)現(xiàn)Parcelable接口,那如果要實(shí)現(xiàn)這個(gè)接口是不是又得一堆代碼呢?當(dāng)然不會(huì),因?yàn)槲覀冇?code>Extension API,因?yàn)橛辛怂覀兛梢允褂没谒麑?shí)現(xiàn)出來的AutoValue: Parcel Extension來實(shí)現(xiàn)Parcelable接口。
使用 Parcel Extension 實(shí)現(xiàn) Parcelable 接口
首先我們需要在項(xiàng)目中集成 AutoValue Parcel Extension
dependencies {
provided 'com.google.auto.value:auto-value:1.2'
apt 'com.google.auto.value:auto-value:1.2'
apt 'com.ryanharter.auto.value:auto-value-parcel:0.2.1'
}
然后再在代碼中加入implements Parcelable即可
@AutoValue
public abstract class Story implements Parcelable{
public abstract int id();
public abstract String title();
public static Story create(int id, String title){
new AutoValue_Story(id,title);
}
}
是不是已經(jīng)體會(huì)到了AutoValue Extension的厲害了?反正我是覺得碉堡了!
有了這個(gè)擴(kuò)展功能,能干的事情就多了,常規(guī)的像對(duì)象序列化成 JSON 字符串,將 JSON 字符串解析成對(duì)象等這些事情就不用自己再去動(dòng)手去寫了,直接用AutoValue生成就可以了,再也不用去寫那些toJson()和fromJson之類的方法了,真是爽歪歪??!
更多的 AutoValue Extension
目前已經(jīng)有人實(shí)現(xiàn)了一些 AutoValue 的擴(kuò)展了,具體的可以看這里。如果這些都無法滿足你的需求,那你可以使用 AutoValue Extension API去自己實(shí)現(xiàn)一個(gè) AutoValue 的擴(kuò)展。