JavaPoet

时间:2024-05-23 08:57:02

【参考链接】

JavaPoet的基本使用http://blog.****.net/crazy1235/article/details/51876192

javapoet——让你从重复无聊的代码中解放出来http://www.jianshu.com/p/95f12f72f69a

 

在看ButterKnife的时候提到JavaPoet,就去看了一下。

Square的一个开源项目,https://github.com/square/javapoet,用于生成.java代码文件。已经有文章翻译了他的readme,见参考链接。

 

下面的示例代码都以javapoet-1.9.0.jar为例

基本使用方式如下

MethodSpecmain = MethodSpec.methodBuilder("main")// main代表方法名

             .addModifiers(Modifier.PUBLIC, Modifier.STATIC)// Modifier//注意类型为javax.lang.model.element.Modifier

             .addParameter(String[].class,"args")//添加string[]类型的名为args的参数

             .addStatement("$T.out.println($S)", System.class,"Hello World")//添加代码

             .build();

 

TypeSpechelloWorld = TypeSpec.classBuilder("HelloWorld")

             .addModifiers(Modifier.PUBLIC)

             .addField(String.class,"greeting", Modifier.PRIVATE, Modifier.FINAL)

             .addMethod(main).build();

 

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

 

try {

      javaFile.writeTo(System.out);

}catch (IOExceptione) {

      e.printStackTrace();

}

生成的源代码文件如下

JavaPoet

 

TypeSpec

即可以生成类,也可能生成接口和枚举等

上面是使用classBuilder来生成类,还可以使用interfaceBuilder来生成接口

TypeSpechelloWorld = TypeSpec.interfaceBuilder("HelloWorld").addModifiers(Modifier.PUBLIC)

             .addField(FieldSpec.builder(String.class,"ONLY_THING_THAT_IS_CONSTANT")

                           .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL).initializer("$S","change")

                           .build())

             .addMethod(MethodSpec.methodBuilder("beep")

                           .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)

                           .build())

             .build();

JavaPoet

使用enumBuilder来生成枚举类

TypeSpechelloWorld = TypeSpec.enumBuilder("Roshambo")

          .addModifiers(Modifier.PUBLIC)

          .addEnumConstant("ROCK")

          .addEnumConstant("SCISSORS")

          .addEnumConstant("PAPER")

          .build();

JavaPoet

FieldSpec

可以通过initializer来指定成员变量的初始值

FieldSpecandroid = FieldSpec.builder(String.class,"android")

          .addModifiers(Modifier.PRIVATE, Modifier.FINAL)

          .initializer("$S + $L","Lollipop v.", 5.0d)//可以使用initializer构造初始值

          .build();

JavaPoet

 

MethodSpec

可以使用addStatement来添加代码片段(并且在其中使用$占位符)

publicclass MethodSpecDemo {

      privatestatic MethodSpec computeRange(Stringname,intfrom,intto, Stringop) {

             return MethodSpec.methodBuilder(name)

                           .returns(int.class)

                           .addStatement("int result = 0")

                           .beginControlFlow("for (int i = $L; i < $L; i++)",from,to)//注意这个地方得是$L

                           .addStatement("result = result $L i",op)

                           .endControlFlow()

                           .addStatement("return result")

                           .build();

      }

 

      publicstaticvoid main(String[]args) {

             TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld")

                           .addModifiers(Modifier.FINAL, Modifier.PUBLIC)

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

                           .build();

             

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

             

             try {

                    javaFile.writeTo(System.out);

             } catch (IOExceptione) {

                    e.printStackTrace();

             }

 

      }

}

JavaPoet

 

还可以直接通过constructorBuilder来生成类的构造函数,此时可以省略指定方法名

MethodSpecflux = MethodSpec.constructorBuilder()//生成构造函数时可以省略指定方法名

          .addModifiers(Modifier.PUBLIC)

          .addParameter(String.class,"greeting")

          .addStatement("this.$L = $L","greeting","greeting")

          .build();

 

TypeSpechelloWorld = TypeSpec.classBuilder("HelloWorld")

   .addModifiers(Modifier.PUBLIC)

   .addField(String.class,"greeting", Modifier.PRIVATE, Modifier.FINAL)

   .addMethod(flux)

   .build();

 

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

 

try {

      javaFile.writeTo(System.out);

}catch (IOExceptione) {

      e.printStackTrace();

}

JavaPoet

 

ParameterSpec

这个其实就是把MethodSpec中的参数单独拿出来构造

ParameterSpecandroid = ParameterSpec.builder(String.class,"android")

          .addModifiers(Modifier.FINAL)

          .build();

 

MethodSpecwelcomeOverlords = MethodSpec.methodBuilder("welcomeOverlords")

   .addParameter(android)//添加方法定义中的参数

   .addParameter(String.class,"robot", Modifier.FINAL)

   .build();

JavaPoet

 

$

在前面的

FieldSpec.Builder.initializer()

MethodSpec.Builder.addStatement()MethodSpec.Builder. beginControlFlow()中已经使用过$占位符

 

$S/$L

$S是用后面的字符串替换前面表达式中的占位符,并且还会带双引号“”

$L是用后面的各种类型替换前面表达式中的占位符,并且不带双引号””

JavaPoet

 

$T

可以使用$T来指代源代码中的数据类型,并且此时会自动import导入相应的类型。

参数既可以传递Class类型,也可以传递com.squareup.javapoet.ClassName类型。

传递Class类型的示例如下

MethodSpectoday = MethodSpec.methodBuilder("today")

   .returns(Date.class)

   .addStatement("return new $T()", Date.class)

   .build();

 

TypeSpechelloWorld = TypeSpec.classBuilder("HelloWorld")

   .addModifiers(Modifier.PUBLIC, Modifier.FINAL)

   .addMethod(today)

   .build();

JavaPoet

传递com.squareup.javapoet.ClassName类型的示例如下

//也可以传递ClassName来当类型名称

ClassNamehoverboard = ClassName.get("com.mattel","Hoverboard");

 

MethodSpectoday = MethodSpec.methodBuilder("tomorrow")

   .returns(hoverboard)

   .addStatement("return new $T()",hoverboard)

   .build();

 

//ClassName叠加泛型//TypeName

ClassNamelist = ClassName.get("java.util","List");

ClassNamearrayList = ClassName.get("java.util","ArrayList");

TypeNamelistOfHoverboards = ParameterizedTypeName.get(list,hoverboard);

 

MethodSpecbeyond = MethodSpec.methodBuilder("beyond")

   .returns(listOfHoverboards)

   .addStatement("$T result = new $T<>()",listOfHoverboards,arrayList)

   .addStatement("result.add(new $T())",hoverboard)

   .addStatement("result.add(new $T())",hoverboard)

   .addStatement("result.add(new $T())",hoverboard)

   .addStatement("return result")

   .build();

 

TypeSpechelloWorld = TypeSpec.classBuilder("HelloWorld")

   .addModifiers(Modifier.PUBLIC, Modifier.FINAL)

   .addMethod(today)

   .addMethod(beyond)

   .build();

JavaPoet

此外还有使用$N来指代方法名,不过因为也可以使用$L来实现,故这里不再举例。