JavaPoet基本使用

276 阅读2分钟

Javapoet用于生成Java文件的API,常用于注解处理过程,该API简单易懂,可以辅助自动化生成一些重复的Java文件,提高工作效率

/*
* TypeSpec:生成类/接口/枚举对象
* MethodSpec:生成方法对象
* ParameterSpec:生成参数对象
* AnnotationSpec:生成注解对象
* FieldSpec:生成变量对象
* CLassName:通过包名+类名生成的对象
* ParameterizedTypeName:泛型类型
* JavaFile:生成类文件的输出类
* */

/*
* $L:Literial,拼接,常用于MethodSpec的addStatement()方法
* $S:Strings,字符串
* $T:Type,可以映射并自动import,常用于java.lang.*的自动导入等
* $N:Nmae,可以引用另外一个MethodSpec的名称作为方法
* */

private static void generate(){
    /*--------------------------- Field --------------------------------*/

    //基本类型变量
    FieldSpec mInt = FieldSpec.builder(int.class,"mInt",Modifier.PUBLIC).initializer("100").build();

    //基本类型包装类型
    FieldSpec mInteger = FieldSpec.builder(Integer.class,"mInteger",Modifier.PUBLIC).initializer("101").build();

    //String类型
    FieldSpec mString = FieldSpec.builder(String.class,"mString",Modifier.PRIVATE).initializer("$S","StringFiled").build();

    //其它类型
    FieldSpec mFile = FieldSpec.builder(File.class,"mFile",Modifier.FINAL).initializer("new File($S)","/data/test.txt").build();

    //构造方法
    MethodSpec mConstructor = MethodSpec.constructorBuilder().addParameter(int.class,"i").addParameter(String.class,"s")
            .addStatement("this.$N = i ;\nthis.$N=s",mInt,mString).build();

    //main方法
    MethodSpec mainMethod = MethodSpec.methodBuilder("main")
            .addParameter(String[].class,"args")
            .returns(Void.TYPE)
            .addModifiers(Modifier.PUBLIC,Modifier.STATIC)
            .addStatement("System.out.println($S)","hello poet !").build();

    //注解方法,重写run方法
    //若只addSuperinterface(Runnable.class) ,不会默认生成重写接口
    ClassName SystemClazz = ClassName.get(System.class);
    MethodSpec overrideMethod = MethodSpec.methodBuilder("run")
            .returns(void.class)
            .addAnnotation(Override.class)
            .addModifiers(Modifier.PUBLIC)
            .addStatement("$T.out.println($S)",SystemClazz,"Runnable Task Start").build();

    //生成接口
    // 注意:1.接口方法必须用Modifier.PUBLIC和Modifier.ABSTRACT修饰;2.接口变量必须用Modifier.PUBLIC,Modifier.STATIC,Modifier.FINAL修饰
    FieldSpec mInterfaceField = FieldSpec.builder(String.class,"mStatus")
            .addModifiers(Modifier.STATIC,Modifier.FINAL, Modifier.PUBLIC)
            .initializer("$S","initStatus")
            .build();
    MethodSpec mInterfaceMethod = MethodSpec.methodBuilder("onStatus")
            .returns(void.class)
            .addModifiers(Modifier.PUBLIC, Modifier.ABSTRACT)
            .addParameter(int.class,"status")
            .build();
    TypeSpec mInterface = TypeSpec.interfaceBuilder("Callback")
            .addField(mInterfaceField)
            .addMethod(mInterfaceMethod)
            .build();

    //枚举类
    TypeSpec mEnum = TypeSpec.enumBuilder("Season")
            .addEnumConstant("Spring")
            .addEnumConstant("Summer")
            .addEnumConstant("Autumn")
            .addEnumConstant("Winter")
            .build();

    //方法内匿名内部类
    //Runnable内部类
    TypeSpec anonymousInnerClass = TypeSpec.anonymousClassBuilder("")
            .addSuperinterface(Runnable.class)
            .addMethod(
                    MethodSpec.methodBuilder("run")
                            .addModifiers(Modifier.PUBLIC)
                            .addAnnotation(Override.class)
                            .returns(void.class)
                            .addStatement("System.out.println($S)"," anonymousInnerClass task start...")
                            .build()
            ).build();

    //带泛型的匿名内部类
    TypeSpec anonymousInnerComparator = TypeSpec.anonymousClassBuilder("")
            .addSuperinterface(ParameterizedTypeName.get(Comparator.class,String.class))
            .addMethod(
                    MethodSpec.methodBuilder("compare")
                    .addModifiers(Modifier.PUBLIC)
                    .returns(int.class)
                    .addParameter(String.class,"a")
                    .addParameter(String.class,"b")
                    .addAnnotation(Override.class)
                    .addStatement("return $N.length()-$N.length()","a","b")
                    .build()
            ).build();

    MethodSpec m1 = MethodSpec.methodBuilder("testInner")
            .returns(void.class)
            .addParameter(ParameterizedTypeName.get(List.class,String.class),"lists")
            .addModifiers(Modifier.PUBLIC)
            .addStatement("new $T($L).start()",Thread.class,anonymousInnerClass)
            .addStatement("$T.sort($N,$L)",Collections.class,"lists",anonymousInnerComparator)
            .build();

    //方法注解
    MethodSpec annotationMethod = MethodSpec.methodBuilder("download")
            .addModifiers(Modifier.PUBLIC)
            .returns(void.class)
            .addAnnotation(
                    AnnotationSpec.builder(GET.class)
                    .addMember("value","$S","/download")
                    .build()
            ).build();


    /*
    * 父类+接口
    * 1.若superclass是Object,生成代码不会写extends Object
    * */
    TypeSpec test = TypeSpec.classBuilder("TestPoet")
            .addModifiers(Modifier.PUBLIC,Modifier.FINAL)
            .addField(mInt)
            .addField(mInteger)
            .addField(mFile)
            .addField(mString)
            .addMethod(mConstructor)
            .addMethod(mainMethod)
            .addMethod(overrideMethod)
            .addMethod(m1)
            .addMethod(annotationMethod)
            .addSuperinterface(Runnable.class)
            .superclass(Object.class)
            .addType(mInterface)
            .addType(mEnum)
            .build();

    JavaFile javaFile = JavaFile.builder("com.lbt.buk.poet",test).build();
    try {
        File file = new File("F:\pj0803\src\com\lbt\buk\poet\TestPoet.java");
        if (file.exists()){
            file.delete();
        }
        javaFile.writeTo(new File("F:\pj0803\src"));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

生成的Java文件如下:

public final class TestPoet implements Runnable {
    public int mInt = 100;

    public Integer mInteger = 101;

    final File mFile = new File("/data/test.txt");

    private String mString = "StringFiled";

    TestPoet(int i, String s) {
        this.mInt = i;
        this.mString = s;
    }

    public static void main(String[] args) {
        System.out.println("hello poet !");
    }

    @Override
    public void run() {
        System.out.println("Runnable Task Start");
    }

    public void testInner(List<String> lists) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(" anonymousInnerClass task start...");
            }
        }).start();
        Collections.sort(lists, new Comparator<String>() {
            @Override
            public int compare(String a, String b) {
                return a.length() - b.length();
            }
        });
    }

    @GET("/download")
    public void download() {
    }

    interface Callback {
        String mStatus = "initStatus";

        void onStatus(int status);
    }

    enum Season {
        Spring,

        Summer,

        Autumn,

        Winter
    }
}