使用 Google AutoValue 自動(dòng)生成代碼

轉(zhuǎn)載請(qǐng)注明出處:http://tedyin.me/2016/04/11/auto-value/

Java中通常定義一個(gè)模型類(lèi)時(shí),需要定義一堆不同類(lèi)型的成員變量受扳,而且為了滿足面向?qū)ο蟮幕咎卣骺备撸忠x一堆相應(yīng)的GetterSetter等方法华望,這個(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ò)展密幔。

參考

An Introduction to AutoValue

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末楔脯,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子胯甩,更是在濱河造成了極大的恐慌昧廷,老刑警劉巖堪嫂,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異麸粮,居然都是意外死亡溉苛,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)弄诲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)愚战,“玉大人,你說(shuō)我怎么就攤上這事齐遵〖帕幔” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵梗摇,是天一觀的道長(zhǎng)拓哟。 經(jīng)常有香客問(wèn)我,道長(zhǎng)伶授,這世上最難降的妖魔是什么断序? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮糜烹,結(jié)果婚禮上违诗,老公的妹妹穿的比我還像新娘。我一直安慰自己疮蹦,他們只是感情好诸迟,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著愕乎,像睡著了一般阵苇。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上感论,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天绅项,我揣著相機(jī)與錄音,去河邊找鬼比肄。 笑死趁怔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的薪前。 我是一名探鬼主播润努,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼示括!你這毒婦竟也來(lái)了铺浇?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤垛膝,失蹤者是張志新(化名)和其女友劉穎鳍侣,沒(méi)想到半個(gè)月后丁稀,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡倚聚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年线衫,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片惑折。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡授账,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惨驶,到底是詐尸還是另有隱情白热,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布粗卜,位于F島的核電站屋确,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏续扔。R本人自食惡果不足惜攻臀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望纱昧。 院中可真熱鬧刨啸,春花似錦、人聲如沸砌些。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)存璃。三九已至,卻和暖如春雕拼,著一層夾襖步出監(jiān)牢的瞬間纵东,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工啥寇, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留偎球,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓辑甜,卻偏偏與公主長(zhǎng)得像衰絮,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子磷醋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理猫牡,服務(wù)發(fā)現(xiàn),斷路器邓线,智...
    卡卡羅2017閱讀 134,651評(píng)論 18 139
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)淌友、插件煌恢、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,093評(píng)論 4 62
  • 愿你們?cè)谝雇聿辉诳奁?這是我來(lái)這個(gè)城市的第二個(gè)月器联,在這個(gè)越來(lái)越熟悉的城市二汛,我感到越來(lái)越迷茫,越來(lái)越渺小主籍,我曾經(jīng)問(wèn)過(guò)...
    YTING_9_8閱讀 205評(píng)論 0 0
  • 兩周前习贫,在知乎回答了一個(gè)有意思的問(wèn)題:為什么我總是愛(ài)上像前女友的女孩? 我想:真慘千元,又一個(gè)被前女友甩的男人苫昌! 陳奕...
    愛(ài)睡覺(jué)的鄧公子閱讀 1,552評(píng)論 4 16
  • 博覽網(wǎng)學(xué)習(xí)筆記: 第三周課程的知識(shí)點(diǎn): 11.組合與繼承 注意:前兩周講的是單個(gè)類(lèi)的設(shè)計(jì),即基于對(duì)象編程幸海。 本周是...
    博覽網(wǎng)小學(xué)員閱讀 200評(píng)論 0 0