Javapoet API(Java代码自动生成)简介及使用思路

1,787 阅读2分钟

目录

基础总结

JavaPoet简介

JavaPoet 是一个生成.Java源文件的Java API。源文件生成在annotation processing 或者和一些元数据,例如文件,数据库设计,协议格式等,进行交互时会很有用。通过代码生成,你能够减少冗余的代码模板,同时保证唯一正确的源文件为元数据。

原文 JavaPoet is a Java API for generating .java source files.

Source file generation can be useful when doing things such as annotation processing or interacting with metadata files (e.g., database schemas, protocol formats). By generating code, you eliminate the need to write boilerplate while also keeping a single source of truth for the metadata.

使用总结

基本使用逻辑,按照正常的新建.java,按照逻辑编写对应的代码,编写的代码替换为Javapoet的语法就可以了,Javapoet 的语法过一遍不用记忆,甚至看一下最小案例,直接开车都木有问题,使用的时候不记得访问GitHub主页对应搜索

引用配置

compile 'com.squareup:javapoet:1.11.1'
<dependency>
  <groupId>com.squareup</groupId>
  <artifactId>javapoet</artifactId>
  <version>1.11.1</version>
</dependency>

最小案例

HelloWorld.java

package com.example.helloworld;

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

JavaPoet.java

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

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
    .addMethod(main)
    .build();

JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)
    .build();

javaFile.writeTo(System.out);

类说明

  • 类生成:TypeSpec.classBuilder("HelloWorld")
  • 接口:TypeSpec.interfaceBuilder("HelloWorld")
  • 方法生成:MethodSpec.methodBuilder("main")
  • 增加访问权限: addModifiers(Modifier.PUBLIC, Modifier.STATIC)
  • 属性:FieldSpec /TypeSpec.addField
  • 参数:ParameterSpec/MethodSpec.addParameter(ParameterSpec)
  • 文档:MethodSpec.addJavadoc

公共

  • String.format() 字符串格式化
    • L for Literals `.addStatement("result = resultL i", op)`
    • S for Strings `.addStatement("returnS", name)`
    • T for Types  ` .addStatement("return newT()", Date.class)会自动import java.util.Date;`包名
      • 手动指定包名:ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");
    • Code block 代码块
      • CodeBlock.builder().add("I ate $2L $1L", "tacos", 3)
      • map
      Map<String, Object> map = new LinkedHashMap<>();
      map.put("food", "tacos");
      map.put("count", 3);
      CodeBlock.builder().addNamed("I ate $count:L $food:L", map)
      
  • Import static 静态导入
JavaFile.builder("com.example.helloworld", hello)
    .addStaticImport(hoverboard, "createNimbus")
    .build();

方法相关

  • 增加代码块

    • addCode
    MethodSpec main = MethodSpec.methodBuilder("main")
        .addCode(""
            + "int total = 0;\n"
            + "for (int i = 0; i < 10; i++) {\n"
            + "  total += i;\n"
            + "}\n")
        .build();
    
    void main() {
      int total = 0;
      for (int i = 0; i < 10; i++) {
        total += i;
      }
    }
    
    • beginControlFlow( { )ddStatementendControlFlow 不用写{\n;}
    MethodSpec main = MethodSpec.methodBuilder("main")
        .addStatement("int total = 0")
        .beginControlFlow("for (int i = 0; i < 10; i++)")
        .addStatement("total += i")
        .endControlFlow()
        .build();
    
  • 函数内部调用

public String byteToHex(int b) {
  char[] result = new char[2];
  result[1] = hexDigit(b & 0xf);
  return new String(result);
}
public char hexDigit(int i) {
  return (char) (i < 10 ? i + '0' : i - 10 + 'a');
}
//-------------------------------------
MethodSpec hexDigit = MethodSpec.methodBuilder("hexDigit")
    .addParameter(int.class, "i")
    .returns(char.class)
    .addStatement("return (char) (i < 10 ? i + '0' : i - 10 + 'a')")
    .build();
MethodSpec byteToHex = MethodSpec.methodBuilder("byteToHex")
    .addParameter(int.class, "b")
    .returns(String.class)
    .addStatement("char[] result = new char[2]")
    .addStatement("result[1] = $N(b & 0xf)", hexDigit)
    .addStatement("return new String(result)")
    .build();
  • 匿名内部类:Anonymous Inner Classes
  • 抽象方法:Modifier.ABSTRACT
public abstract class HelloWorld {
  protected abstract void flux();
}
//-------------------------
MethodSpec flux = MethodSpec.methodBuilder("flux")
    .addModifiers(Modifier.ABSTRACT, Modifier.PROTECTED)
    .build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
    .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
    .addMethod(flux)
    .build();
  • 构造方法
 public HelloWorld(String greeting) {
    this.greeting = greeting;
  }
//------------------------------
MethodSpec flux = MethodSpec.constructorBuilder()
    .addModifiers(Modifier.PUBLIC)
    .addParameter(String.class, "greeting")
    .addStatement("this.$N = $N", "greeting", "greeting")
    .build();
  • MethodSpec.addAnnotation(Override.class)

其他

  • 参数: Parameters
void welcomeOverlords(final String android, final String robot) {
}
//-------------------------------
ParameterSpec android = ParameterSpec.builder(String.class, "android")
    .addModifiers(Modifier.FINAL)
    .build();
MethodSpec welcomeOverlords = MethodSpec.methodBuilder("welcomeOverlords")
    .addParameter(android)
    .addParameter(String.class, "robot", Modifier.FINAL)
    .build();
  • 属性:FieldSpec
FieldSpec android = FieldSpec.builder(String.class, "android")
    .addModifiers(Modifier.PRIVATE, Modifier.FINAL)
    .initializer("$S + $L", "Lollipop v.", 5.0d)
    .build();
  • Javadoc

JavaPoet 官网