使用 Google AutoValue 自動生成代碼

轉載請注明出處:http://tedyin.me/2016/04/11/auto-value/

Java中通常定義一個模型類時,需要定義一堆不同類型的成員變量,而且為了滿足面向對象的基本特征,又要定義一堆相應的GetterSetter等方法,這個過程是非??菰锏囊獙懸欢褬影宕a。雖然現(xiàn)在 IDE 可以很好的幫我們生成這些樣板代碼,但是如果看到一個模型類里面有這么一堆的方法,總覺是會覺得不夠清晰。

我只想知道這個模型有哪些屬性,以及特殊的方法,并不想知道大家都有的東西,你卻非要讓我看。。。

好了,現(xiàn)在有辦法可以解決這個問題了,使用 Google 開源的 AutoValue 就可以解決上述煩惱,而且最近AutoValue項目支持了大家期待已久的Extension API,使得AutoValue更加靈活,至于這個Extension API是干啥的后面會講到,現(xiàn)在暫時不用去關心他。

普通的 Java 模型

我們這里舉個故事(Story)的例子,一個故事模型擁有一個id,以及一個title。下面我們來看下用Java代碼來表示該模型的寫法。

不太嚴謹?shù)膶懛?/h3>

我們先來看下一般情況下我們是怎么定義這個 POJO 的業(yè)務模型的。

public class Story{
  public int id;
  public String title;
}

上面的寫法非常簡單,不過有些情況下可能會有問題,比如對象比較時,而且也不符合封裝的要求,不過一般情況下業(yè)務邏輯簡單,還處在快速迭代的時候這樣寫也沒什么問題,而且重點是他 只有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;
  }
}

這樣寫符合了面向對象的基本特征封裝的要求,但是如果這個Story是在列表或者集合中有用到比較的時候,這么寫是有問題的,應該繼續(xù)覆蓋hashCode()equals()方法,如果有特殊格式的輸出,還得覆蓋toString()方法。

把這些東西都補全的寫法如下:

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);
  }
}

上面的版本是一個比較完整的模型寫法,相比起最初的版本,代碼多了不少從原來的4行變成了現(xiàn)在的39行!
OMG!現(xiàn)在的版本還沒有實現(xiàn)Parcelable接口,如果再在他的基礎上實現(xiàn)Parcelable接口,那代碼又得增加十幾行,想想都心累啊。

使用AutoValue拯救你的代碼

我本想要一個只有幾行的模型類,但是出于各方面原因,我得到了一個幾十行代碼的模型類,為了解決這個問題偉大的Google開發(fā)了AutoValue這個庫來自動生成這些樣板代碼,解放我們的雙手,讓我們把更多的精力放在更重要的事情上。

使用AutoValue

使用方法很簡單,只需要在你的項目中引入AutoValue的插件即可

dependencies {
  apt 'com.google.auto.value:auto-value:1.2'
}

然后在代碼中使用@AutoValue注解來指定哪個類需要生成類似于上面的樣板代碼。下面我們使用AutoValue來重新實現(xiàn)一下Story模型。

@AutoValue
public abstract class Story{
  public abstract int id();
  public abstract String title();
}

使用@AutoValue注解后,AutoValue會生成一個AutoValue_你的類名為名稱的類,這個類是包級私有的,他里面有私有的成員變量,對應的構造函數(shù),以及重寫的hashCode()、equals()toString()方法,而且這些方法都是被測試過的確保無誤的,你可以放心的使用。由于這個生成的子類是包級私有的,所以這里在給Story提供構造方法的時候需要提供一個靜態(tài)的構造方法,代碼如下:

@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后,這短短幾行代碼就完成了上面幾十行代碼干的事,而且這樣生成出來的代碼都是被測試過準確無誤的,這也避免了一些因為手誤或者邏輯錯誤導致的BUG的產(chǎn)生,是不是很爽?必須很爽??!

But... 我們要更爽一點!

AutoValue Extension API

大家注意到?jīng)]有上面使用AutoValue實現(xiàn)的Story模型并沒有實現(xiàn)Parcelable接口,那如果要實現(xiàn)這個接口是不是又得一堆代碼呢?當然不會,因為我們有Extension API,因為有了他我們可以使用基于他實現(xiàn)出來的AutoValue: Parcel Extension來實現(xiàn)Parcelable接口。

使用 Parcel Extension 實現(xiàn) Parcelable 接口

首先我們需要在項目中集成 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)體會到了AutoValue Extension的厲害了?反正我是覺得碉堡了!
有了這個擴展功能,能干的事情就多了,常規(guī)的像對象序列化成 JSON 字符串,將 JSON 字符串解析成對象等這些事情就不用自己再去動手去寫了,直接用AutoValue生成就可以了,再也不用去寫那些toJson()fromJson之類的方法了,真是爽歪歪啊!

更多的 AutoValue Extension

目前已經(jīng)有人實現(xiàn)了一些 AutoValue 的擴展了,具體的可以看這里。如果這些都無法滿足你的需求,那你可以使用 AutoValue Extension API去自己實現(xiàn)一個 AutoValue 的擴展。

參考

An Introduction to AutoValue

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容