android:[2]代码生成器Javapoet

2025-09-10 20:12:46

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.generate;public class HelloWorld {}

在javapoet中.java文件对应JavaFile

class类对应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 getMessage = 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

声明:本网站引用、摘录或转载内容仅供网站访问者交流或参考,不代表本站立场,如存在版权或非法内容,请联系站长删除,联系邮箱:site.kefu@qq.com。
猜你喜欢