轉(zhuǎn)載請(qǐng)注明出處:http://tedyin.me/2016/04/11/auto-value/
在Java
中通常定義一個(gè)模型類(lèi)時(shí),需要定義一堆不同類(lèi)型的成員變量受扳,而且為了滿足面向?qū)ο蟮幕咎卣骺备撸忠x一堆相應(yīng)的Getter
和Setter
等方法华望,這個(gè)過(guò)程是非忱抵郏枯燥的要寫(xiě)一堆樣板代碼宾抓。雖然現(xiàn)在 IDE 可以很好的幫我們生成這些樣板代碼石洗,但是如果看到一個(gè)模型類(lèi)里面有這么一堆的方法讲衫,總覺(jué)是會(huì)覺(jué)得不夠清晰涉兽。
我只想知道這個(gè)模型有哪些屬性枷畏,以及特殊的方法拥诡,并不想知道大家都有的東西,你卻非要讓我看宾娜。前塔。华弓。
好了寂屏,現(xiàn)在有辦法可以解決這個(gè)問(wèn)題了娜搂,使用 Google 開(kāi)源的 AutoValue 就可以解決上述煩惱百宇,而且最近AutoValue
項(xiàng)目支持了大家期待已久的Extension API
昌粤,使得AutoValue
更加靈活啄刹,至于這個(gè)Extension API
是干啥的后面會(huì)講到膊升,現(xiàn)在暫時(shí)不用去關(guān)心他廓译。
普通的 Java 模型
我們這里舉個(gè)故事(Story)的例子非区,一個(gè)故事模型擁有一個(gè)id
征绸,以及一個(gè)title
淆衷。下面我們來(lái)看下用Java
代碼來(lái)表示該模型的寫(xiě)法祝拯。
不太嚴(yán)謹(jǐn)?shù)膶?xiě)法
我們先來(lái)看下一般情況下我們是怎么定義這個(gè) POJO 的業(yè)務(wù)模型的佳头。
public class Story{
public int id;
public String title;
}
上面的寫(xiě)法非常簡(jiǎn)單,不過(guò)有些情況下可能會(huì)有問(wèn)題亭珍,比如對(duì)象比較時(shí)块蚌,而且也不符合封裝的要求,不過(guò)一般情況下業(yè)務(wù)邏輯簡(jiǎn)單纱控,還處在快速迭代的時(shí)候這樣寫(xiě)也沒(méi)什么問(wèn)題,而且重點(diǎn)是他 只有4行代碼尔店!
比較規(guī)范的寫(xiě)法
下面看下正常情況下的寫(xiě)法:
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;
}
}
這樣寫(xiě)符合了面向?qū)ο蟮幕咎卣?code>封裝的要求,但是如果這個(gè)Story
是在列表或者集合中有用到比較的時(shí)候共螺,這么寫(xiě)是有問(wèn)題的藐不,應(yīng)該繼續(xù)覆蓋hashCode()
和equals()
方法涎嚼,如果有特殊格式的輸出贡耽,還得覆蓋toString()
方法阱冶。
把這些東西都補(bǔ)全的寫(xiě)法如下:
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è)比較完整的模型寫(xiě)法,相比起最初的版本尘颓,代碼多了不少?gòu)脑瓉?lái)的4
行變成了現(xiàn)在的39
行!
OMG!現(xiàn)在的版本還沒(méi)有實(shí)現(xiàn)Parcelable
接口尤莺,如果再在他的基礎(chǔ)上實(shí)現(xiàn)Parcelable
接口涂滴,那代碼又得增加十幾行柔纵,想想都心累啊进苍。
使用AutoValue拯救你的代碼
我本想要一個(gè)只有幾行的模型類(lèi),但是出于各方面原因,我得到了一個(gè)幾十行代碼的模型類(lèi),為了解決這個(gè)問(wèn)題偉大的Google
開(kāi)發(fā)了AutoValue
這個(gè)庫(kù)來(lái)自動(dòng)生成這些樣板代碼罩引,解放我們的雙手横浑,讓我們把更多的精力放在更重要的事情上洒缀。
使用AutoValue
使用方法很簡(jiǎn)單脚猾,只需要在你的項(xiàng)目中引入AutoValue
的插件即可
dependencies {
apt 'com.google.auto.value:auto-value:1.2'
}
然后在代碼中使用@AutoValue
注解來(lái)指定哪個(gè)類(lèi)需要生成類(lèi)似于上面的樣板代碼。下面我們使用AutoValue
來(lái)重新實(shí)現(xiàn)一下Story
模型。
@AutoValue
public abstract class Story{
public abstract int id();
public abstract String title();
}
使用@AutoValue
注解后,AutoValue
會(huì)生成一個(gè)AutoValue_你的類(lèi)名
為名稱(chēng)的類(lèi)赡鲜,這個(gè)類(lèi)是包級(jí)私有
的空厌,他里面有私有的成員變量庐船,對(duì)應(yīng)的構(gòu)造函數(shù),以及重寫(xiě)的hashCode()
嘲更、equals()
和toString()
方法筐钟,而且這些方法都是被測(cè)試過(guò)的確保無(wú)誤的,你可以放心的使用赋朦。由于這個(gè)生成的子類(lèi)是包級(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后宠哄,這短短幾行代碼就完成了上面幾十行代碼干的事壹将,而且這樣生成出來(lái)的代碼都是被測(cè)試過(guò)準(zhǔn)確無(wú)誤的,這也避免了一些因?yàn)槭终`或者邏輯錯(cuò)誤導(dǎo)致的BUG的產(chǎn)生毛嫉,是不是很爽诽俯?必須很爽啊狱庇!
But... 我們要更爽一點(diǎn)!
AutoValue Extension API
大家注意到?jīng)]有上面使用AutoValue
實(shí)現(xiàn)的Story
模型并沒(méi)有實(shí)現(xiàn)Parcelable
接口恶耽,那如果要實(shí)現(xiàn)這個(gè)接口是不是又得一堆代碼呢密任?當(dāng)然不會(huì),因?yàn)槲覀冇?code>Extension API偷俭,因?yàn)橛辛怂覀兛梢允褂没谒麑?shí)現(xiàn)出來(lái)的AutoValue: Parcel Extension來(lái)實(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
的厲害了?反正我是覺(jué)得碉堡了涌萤!
有了這個(gè)擴(kuò)展功能淹遵,能干的事情就多了,常規(guī)的像對(duì)象序列化成 JSON 字符串负溪,將 JSON 字符串解析成對(duì)象等這些事情就不用自己再去動(dòng)手去寫(xiě)了透揣,直接用AutoValue
生成就可以了,再也不用去寫(xiě)那些toJson()
和fromJson
之類(lèi)的方法了川抡,真是爽歪歪胺妗!
更多的 AutoValue Extension
目前已經(jīng)有人實(shí)現(xiàn)了一些 AutoValue 的擴(kuò)展了崖堤,具體的可以看這里侍咱。如果這些都無(wú)法滿足你的需求,那你可以使用 AutoValue Extension API
去自己實(shí)現(xiàn)一個(gè) AutoValue 的擴(kuò)展密幔。