手抄报 安全手抄报 手抄报内容 手抄报图片 英语手抄报 清明节手抄报 节约用水手抄报

android:[2]代码生成器Javapoet

时间:2024-10-12 11:00:51

Javapoet是square开发的一款java代码生成器,不同于Asm, Javassist等框架修改生成.class文件直接操作字节码,javapoet直接生成java源码

工具/原料

jdk

android studio

javapoet

环境搭建

1、在项目中新建一个java library module名字为app

android:[2]代码生成器Javapoet

2、在app的build.gradle中添加javapoet依赖[推荐]compile 'com.squareup:javapoet:1.7.0'或者你也可以将javapoet的jar包下载下来直接放入app的libs目录javapoet的下载地址为http://mvnrepository.com/artifact/com.squareup/javapoet/1.7.0直接点击Download (JAR)即可下载

android:[2]代码生成器Javapoet

3、添加好依赖后刷新一下项目依赖即可生效,

代码编写

1、接下来我们要生成一个HelloWorld.java内容为package com.example.ge荏鱿胫协nerate;public class HelloWorld {}在javapoet中.java文件对应JavaFileclass类对应TypeSpec因此创建HelloWorld类的代码为TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC) .build();其中classBuilder传入类名,addModifiers传入修饰语创建HelloWorld.java的代码为PACKAGE = "com.example.generate"JavaFile javaFile = JavaFile.builder(PACKAGE, typeSpec).build();我们将创建的内容打印到控制台javaFile.writeTo(System.out);可以看到输出的内容为package com.example.generate;public class HelloWorld {}

android:[2]代码生成器Javapoet
android:[2]代码生成器Javapoet

2、一般我们生成的代码最终会保存为文件,javapoet将生成的代码保存成文件的方法也是调用JavaFile的writeTo方法,我们直接传入需要保存的目录即可javaFile.writeTo(new File("app/src/main/java"));

android:[2]代码生成器Javapoet
android:[2]代码生成器Javapoet

3、HelloWorld.java按照我们的要求生成了,现在我们将HelloWorld.java的内容改造一下在HelloWorld.java中添加Parent抽象类给HelloWorld类添加final修改语,并实现Serializable接口和Parent类并重写Parent的getMessage方法并添加一个名为message的static final 修饰的String类型变量,变量的值为Hello, JavaPoet!同时实现main方法,并在方法中通过System.out.println打印Hello, JavaPoet!我们期望生成的代码如下package com.example.generate;import java.io.Serializable;public final class HelloWorld extends Parent implements Serializable{ private static final String message = "Hello, JavaPoet!"; public static void main(String[] args){ System.out.println("Hello, JavaPoet!"); } @Override protected String getMessage() { return message; }}abstract class Parent{ protected abstract String getMessage();}

android:[2]代码生成器Javapoet

4、首先我们生成protected abstract String getMessage();方法MethodSpec getMessag髫潋啜缅e = MethodSpec.methodBuilder("getMessage") .addModifiers(Modifier.PROTECTED) .addModifiers(Modifier.ABSTRACT) .returns(String.class) .build();然后生成Parent类并添加getMessage方法TypeSpec parent = TypeSpec.classBuilder("Parent") .addModifiers(Modifier.ABSTRACT) .addMethod(getMessage) .build();这样Parent类的生成代码就写好了接下来写HelloWorld的实现代码,首先给HelloWorld添加final修饰,并实现接口和继承Parent类TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.FINAL) .addSuperinterface(Serializable.class) .build();接下生成message变量FieldSpec message = FieldSpec.builder(String.class, "message") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addModifiers(Modifier.FINAL) .initializer("\"Hello, JavaPoet!\"") .build();然后重载getMessage方法,并添加@Override注解MethodSpec getMessageOvrerride = MethodSpec.methodBuilder("getMessage") .addAnnotation(Override.class) .addModifiers(Modifier.PROTECTED) .returns(String.class) .addStatement("return message") .addModifiers() .build();再添加main方法,并在main方法中打印字符串MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(void.class) .addParameter(String[].class, "args") .addStatement("System.out.println(\"Hello, JavaPoet!\")") .build();最后将生成的main方法,重写的getMessage, 和message字段添加到HelloWorld中TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.FINAL) .superclass(ClassName.get(PACKAGE, parent.name)) .addSuperinterface(Serializable.class) .addType(parent) .addField(message) .addMethod(main) .addMethod(getMessageOvrerride) .build();编译运行并查看生成结果,发现生成的代码和预期的有点差别package com.example.generate;import java.io.Serializable;import java.lang.Override;import java.lang.String;public final class HelloWorld extends Parent implements Serializable { public static final String message = "Hello, JavaPoet!"; public static void main(String[] args) { System.out.println("Hello, JavaPoet!"); } @Override protected String getMessage() { return message; } abstract class Parent { protected abstract String getMessage(); }}生成的代码变成了HelloWorld的内部类,这并不是我们期望的结果,查看javapoet文档也没有找到解决方法,通过查看JavaFile代码我们发现只能传入一个TypeSpec,如果要达到我们期望的结果只有自己重新实现JavaFile。

android:[2]代码生成器Javapoet

5、步骤4中我们发现TypeSpec.Builder下的addType添加的只能是内部类,并不能实现一个.java文件中并列存在多个类,这里给出重写的JavaFile实现JavaFileFixed, 重写的类中保存了多个TypeSpec实例,Builder中添加了两个额外的addType方法,JavaFileFixed代码请到步骤8给的链接中去查看

6、将生成HelloWorld代码中的.addType(parent)方法去掉,应为我们不想Parent类成为HelloWorld的内部类,同时将JavaFile javaFile = JavaFile.builder(PACKAGE, typeSpec).build();替换为JavaFileFixed javaFile = JavaFileFixed.builder(PACKAGE, typeSpec).addType(parent).build();新实现的代码中builder(PACKAGE, typeSpec),typeSpec将作为顶级类,也是.java文件的名字addType(parent)中的parent将会作为typeSpec的并列类,更具java语法一个.java文件中只能有一个public顶积类,因此parent不能是public的,以下是修改后的代码MethodSpec getMessage = MethodSpec.methodBuilder("getMessage") .addModifiers(Modifier.PROTECTED) .addModifiers(Modifier.ABSTRACT) .returns(String.class) .build();TypeSpec parent = TypeSpec.classBuilder(ClassName.get(PACKAGE, "Parent")) .addModifiers(Modifier.ABSTRACT) .addMethod(getMessage) .build();FieldSpec message = FieldSpec.builder(String.class, "message") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .addModifiers(Modifier.FINAL) .initializer("\"Hello, JavaPoet!\"") .build();MethodSpec getMessageOvrerride = MethodSpec.methodBuilder("getMessage") .addAnnotation(Override.class) .addModifiers(Modifier.PROTECTED) .returns(String.class) .addStatement("return message") .addModifiers() .build();MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.PUBLIC, Modifier.STATIC) .returns(void.class) .addParameter(String[].class, "args") .addStatement("System.out.println(\"Hello, JavaPoet!\")") .build();TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld") .addModifiers(Modifier.PUBLIC) .addModifiers(Modifier.FINAL) .superclass(ClassName.get(PACKAGE, parent.name)) .addSuperinterface(Serializable.class) //.addType(parent) .addField(message) .addMethod(main) .addMethod(getMessageOvrerride) .build();JavaFileFixed javaFile = JavaFileFixed.builder(PACKAGE, typeSpec).addType(parent).build();try { javaFile.writeTo(new File("app/src/main/java"));} catch (IOException e) { e.printStackTrace();}

android:[2]代码生成器Javapoet

7、修改后重新编译运行查看结果package com.example.generate;import java.io.Serializable;import java.lang.Override;import java.lang.String;public final class HelloWorld extends Parent implements Serializable { public static final String message = "Hello, JavaPoet!"; public static void main(String[] args) { System.out.println("Hello, JavaPoet!"); } @Override protected String getMessage() { return message; }}abstract class Parent { protected abstract String getMessage();}与我们预期的效果一致

android:[2]代码生成器Javapoet

8、文章中所有源代码:https://git.oschina.net/jackyanngo/JavaPoetSample.git

© 手抄报圈