JavaPoet使用介紹

Square 出品,必屬精品

沒錯,有事沒事就要抱大腿,JavaPoet是以面向?qū)ο蟮姆绞絹砩?java源代碼的一個api庫。

背景

在使用APT生產(chǎn)Java源碼的過程中,我們通常的做法是手動寫代碼,但是這樣確實不符合程序員的性格啊,畢竟手動填進去的代碼,萬一少個括號或者分號,肯定編譯不過去,還要再改。
恩,JavaPoet因此應運而生。具體原理這里就不講了,就是生產(chǎn)字符串信息,而其中的背景以及設計的思路確實是值得學習的。當時不知道這個類庫的時候還傻傻的一行一行寫字符串... (捂臉逃

實際應用

下面舉個栗子:

public final class HelloWorld {
  public static void main(String[] args) {
    System.out.println("Hello, JavaPoet!");
  }

其對應的生產(chǎn)方式代碼如下:

//方法生產(chǎn)
MethodSpec main = MethodSpec.methodBuilder("main")
    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
    .returns(void.class)
    .addParameter(String[].class, "args")
    .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
    .build();
//類生產(chǎn)
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
    .addMethod(main)
    .build();
//.java 文件生產(chǎn)
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
    .build();

當我們的類方法體里面并沒有模板的方法,類型或者參數(shù)表達式,是固定不變的,我們可以這樣寫:

MethodSpec main = MethodSpec.methodBuilder("main")
    .addCode(""
        + "int total = 0;\n"
        + "for (int i = 0; i < 10; i++) {\n"
        + "  total += i;\n"
        + "}\n")
    .build();

生產(chǎn)的代碼是這樣的:

void main() {
  int total = 0;
  for (int i = 0; i < 10; i++) {
    total += i;
  }
}

或者有參數(shù)是可變的,這樣寫:

private MethodSpec computeRange(String name, int from, int to, String op) {
  return MethodSpec.methodBuilder(name)
      .returns(int.class)
      .addStatement("int result = 0")
      .beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)")
      .addStatement("result = result " + op + " i")
      .endControlFlow()
      .addStatement("return result")
      .build();
}

然后調(diào)用:

computeRange("multiply10to20", 10, 20, "*")

生產(chǎn)的代碼是這樣的:

int multiply10to20() {
  int result = 0;
  for (int i = 10; i < 20; i++) {
    result = result * i;
  }
  return result;
}

以上大概是如何使用的一些栗子,然后我們來想一下這個api是如何實現(xiàn)的。

我要如何寫出這樣的被STAR 3500以上的API

哈哈,這個標題寫的有點重了,不過還是大致說下:

  1. 堅持。 肯定不是一蹴而就的,這個項目被維護了兩年,到現(xiàn)在還一直有提交。可是國內(nèi)的某些githuber ,一次提交就完事了,以后再不更新,有人提isuue 也愛答不理,功利心太強。
  2. 想法很重要,行動更重要。這里說白了就是字符串拼接,但是人家發(fā)現(xiàn)了這個問題,并且切實的解決了這個問題,確實是高。Let me read the fucking code
  3. java類結(jié)構(gòu)分析
    一個.java 文件,大致可以做一下切分如下圖:
一個java類

然后我們來看下注解是如何添加到方法,變量以及類上面的。
在FiledSpec中,通過一個建造者模式,添加一個AnnotationSpec


    public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) {
      checkArgument(annotationSpecs != null, "annotationSpecs == null");
      for (AnnotationSpec annotationSpec : annotationSpecs) {
        this.annotations.add(annotationSpec);
      }
      return this;
    }

在MethodSpec 和 TypeSpec中,同樣的:

 public Builder addAnnotations(Iterable<AnnotationSpec> annotationSpecs) {
      checkArgument(annotationSpecs != null, "annotationSpecs == null");
      for (AnnotationSpec annotationSpec : annotationSpecs) {
        this.annotations.add(annotationSpec);
      }
      return this;
    }

在FliedSpec中生產(chǎn)代碼:

  void emit(CodeWriter codeWriter, Set<Modifier> implicitModifiers) throws IOException {
    codeWriter.emitJavadoc(javadoc);
    codeWriter.emitAnnotations(annotations, false);
    codeWriter.emitModifiers(modifiers, implicitModifiers);
    codeWriter.emit("$T $L", type, name);
    if (!initializer.isEmpty()) {
      codeWriter.emit(" = ");
      codeWriter.emit(initializer);
    }
    codeWriter.emit(";\n");
  }

這里我們分析下實現(xiàn):可以看到,根據(jù)上面的圖例,合理的抽象出對象,使用合理的設計模式,寫的代碼也易于理解。確實有很多值得借鑒和學習的地方。

總結(jié)

臨淵羨魚不如退而結(jié)網(wǎng),共勉之。

參考

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

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,940評論 25 709
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,539評論 19 139
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內(nèi)部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,643評論 18 399
  • 無論怎么樣,無論什么時候我都會等你。等著和你一起走未來的路。佳音,我等你。因為我愛你。
    愛運動愛排球閱讀 217評論 0 1
  • 原文地址:https://dev.mysql.com/doc/refman/5.7/en/data-type-de...
    翼徳閱讀 4,798評論 0 2

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