javapoet使用

来源:互联网 发布:蜗居宋思明知乎 编辑:程序博客网 时间:2024/06/06 01:41

javapoet简介

javapoet是一个用于生成.java源文件的Java API。相关的还有javaWriter是javapoet的一个分支,ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。javapoet常用来做编译时java文件生成,在butterknife和dagger中使用。

javapoet中API的使用

1.我们动态生成类使用TypeSpec.classBuilder()方法,在classBuilder方法中参数类型为String或者ClassName,就是生成class类的名称,ClassName是JavaPoet中定义的一个对象,可以通过ClassName.get()获取,在这个里面可以传入包名和类名组成一个全路径名称,ClassName.get(“www.hikvision.com”,TestBuilder)组成一个www.hikvision.com.TestBuilder全路径名。

     TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .build();    String path = Main.class.getResource("/").getPath();    File file = new File(path);    JavaFile.builder("www.hikvision.com",build).build().writeTo(file);

#
在上面classBuilder中是类的名称,JavaFile.builder(“www.hikvision.com”,build).build().writeTo(file);”www.hikvision.com”是包名。生成文件如下

    package www.hikvision.com;    class TestBuilder {    }

2.可以通过修饰符来修饰一个类,Modifier是修饰符枚举,里面定义了 PUBLIC,PROTECTED,PRIVATE,ABSTRACT,DEFAULT,STATIC,FINAL,
TRANSIENT,VOLATILE,SYNCHRONIZED,NATIVE,STRICTFP;12个修饰符类addModifiers()方法调用

    TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)            .build();   

3.在生成类中添加字段,通过FieldSpec.builder()来生成字段,在builder定义字段的类型,名称和修饰符,再通过addFiled()添加到类中

          TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)           .addField(FieldSpec.builder(TypeName.BOOLEAN,"isOpen",Modifier.PROTECTED).build())           .build();

4.构造方法的添加,通过addMethod()方法添加一个MethodSpec对象,可以通过MethodSpec.constructorBuilder()生成一个构造方法,也可生通过MethodSpec.methodBuilder()成一个普通方法,记得在生成构造方法时通过修饰符addModifiers()修饰构造方法

     TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)

.addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).build())
.build();

5.生成类中使用泛型,使用addTypeVariable方法,可以通过添加TypeVariableName来设置类的泛型
TypeVariableName typeVariableName=TypeVariableName.get(“T”);

         TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)            .addTypeVariable(typeVariableName)            .build();

6.泛型约束例如,还是可以通过TypeVariableName来设置

            TypeVariableName typeVariableName=TypeVariableName.get("T",TypeName.get(Main.class));      TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)            .addTypeVariable(typeVariableName)            .build();

7.实现接口通过addSuperinterface()方法实现接口实现

     TypeSpec build = TypeSpec.classBuilder("TestBuilder")             .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)             .addSuperinterface(ITest.class)             .build();

8.继承类superclass()

     TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)            .superclass(Test.class)             .build();

9.接口泛型约束 public class A implement B{}这种在接口上面添加泛型约束,通过addSuperinterface()方法和ParameterizedTypeName结合使用,通过ParameterizedTypeName包裹接口类和泛型来实现

            ParameterizedTypeName             parameterizedTypeName=ParameterizedTypeName.get(ITest.class,Main.class);     TypeSpec build = TypeSpec.classBuilder("TestBuilder")            .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)            .addSuperinterface(parameterizedTypeName)            .build();

10.普通方法添加通过addMethod方法,使用MethodSpec.methodBuilder()添加方法

     MethodSpec testMethod = MethodSpec.methodBuilder("test")            .addModifiers(Modifier.PUBLIC)            .build();     TypeSpec build = TypeSpec.classBuilder("TestBuilder")              .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)              .addMethod(testMethod)              .build();

11.返回值添加是MethodSpec.returns()

      MethodSpec testMethod = MethodSpec.methodBuilder("test")            .addModifiers(Modifier.PUBLIC)            .returns(Main.class)            .build();

12.方法参数添加MethodSpec.addParameter

     CodeBlock codeBlock=CodeBlock.builder()            .add("T temp=t;\n")            .build();    MethodSpec testMethod = MethodSpec.methodBuilder("test")            .addModifiers(Modifier.PUBLIC)            .addParameter(typeVariableName,"t")             .build();

13.代码块$L使用

    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 = $L; i < $L; i++)", from, to)          .addStatement("result = result $L i", op)          .endControlFlow()          .addStatement("return result")          .build();    }

13.代码块添加有两种方法addCode()和addStatement()两种方式,在addCode中可以创建一个CodeBlock代码块添加代码,在生成代码块是可以使用format对代码进行替换,在javapoet中主要用S,T,LN四种,TS主要替换字符串,LN替换名字,一般调用方法可以通过$N替换。https://github.com/square/javapoet这个是javapoet在github托管网址,有javapoet基础用法,关于泛型使用没有讲解,可以学习butterknife中泛型使用https://github.com/JakeWharton/butterknife,也可以看下我GitHub关于编译时注解demo,https://github.com/starsquare/star_sky里面有相关泛型的引用。

    CodeBlock codeBlock=CodeBlock.builder()            .add("T temp=t;\n")            .build();     MethodSpec testMethod = MethodSpec.methodBuilder("test")              .addModifiers(Modifier.PUBLIC)              .addCode(codeBlock)              .addStatement("$T m=new $T()",Main.class,Main.class)              .build();