您的位置:首页 > 移动开发 > Android开发

Android APT开发教程 二 JavaPoet生成 .java源文件的Java API

2018-01-20 15:38 513 查看
github项目代码地址
https://github.com/979451341/TestAPT
这篇说如何生成Java文件,所使用的就是JavaPoet这个API提供的代码,让我们来学习如何去使用它。

1.添加定死的代码

比如我想要生成如下代码的java文件

package com.example;

public final class TestClass {

  void main() {

    int total = 0;

    for (int i = 0; i < 10; i++) {

      total += i;

    }

  }

}

那生成代码如下

        MethodSpec main = MethodSpec.methodBuilder("main")

                .addCode(""

                        + "int total = 0;\n"

                        + "for (int i = 0; i < 10; i++) {\n"

                        + "  total += i;\n"

                        + "}\n")

                .build();

        TypeSpec testClass = TypeSpec.classBuilder("TestClass")

                .addModifiers(Modifier.PUBLIC,Modifier.FINAL)

                .addMethod(main)

                .build();

        JavaFile javaFile = JavaFile.builder("com.example",testClass)

                .build();

通过以上代码可以看出,JavaPoet很多时候都是用的Builder模式来构建代码,这个MethodSpec是用来新建函数的,通过methodBuilder取函数名并通过addCode来添加代码,TypeSpec则是用来生成类,通过classBuilder来创建和去类名,通过addModifiers来规定类的属性,然后通过addMethod添加函数。最后是通过JavaFile来生成相应包下的java文件,指定了包名和类。

后面我会重点说MethodSpec如何用,就不贴完整代码了

2.引用自己给参数

以上代码还有另一种方法生成,addStatement() 负责分号和换行,beginControlFlow() + endControlFlow() 需要一起使用,相当于{ }

MethodSpec main = MethodSpec.methodBuilder("main")

    .addStatement("int total = 0")

    .beginControlFlow("for (int i = 0; i < 10; i++)")

    .addStatement("total += i")

    .endControlFlow()

    .build();

还能给生成有参数的函数

private MethodSpec computeRange(String name, int from, int to, int op) {

  return MethodSpec.methodBuilder(name)

      .returns(int.class)

      .addStatement("int result = 0")

      .beginControlFlow("for (int i = " + from + "; i < " + to + "; i++)")

      .addStatement("result = result +" + op + "+ i")

      .endControlFlow()

      .addStatement("return result")

      .build();

}

还有另一种生成有参数的函数,Literals 直接写在输出代码中,没有转义。 它的类型可以是所有基础类型。

private MethodSpec computeRange(String name, int from, int to, int 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();

}

然后$S 表示可以一个 string

private static MethodSpec whatsMyName(String name) {

  return MethodSpec.methodBuilder(name)

      .returns(String.class)

      .addStatement("return $S", name)

      .build();

}

3.导包

通过 $T 进行映射,会自动import声明

MethodSpec today = MethodSpec.methodBuilder("today")

    .returns(Date.class)

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

    .build();

ClassName 可以识别任何声明类。具体看下面的例子:

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

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

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

TypeName listOfHoverboards = ParameterizedTypeName.get(list, hoverboard);

MethodSpec beyond = 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();

还有import static

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

import static com.mattel.Hoverboard.Boards.*;

还有生成的函数引用自己生成的函数

通过$N来引用 hexDigit()方法作为一个参数:

addStatement("result[1] = $N(1)", hexDigit)

4.构造函数

addParameter(String.class, "greeting")

public HelloWorld(String greeting)

还可以指定类型

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

5.成员变量Fields

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

    .addModifiers(Modifier.PRIVATE, Modifier.FINAL)

    .build();

TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")

    .addModifiers(Modifier.PUBLIC)

    .addField(android)

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

    .build();

public class HelloWorld {

  private final String android;

  private final String robot;

}

6.接口

TypeSpec helloWorld = TypeSpec.interfaceBuilder("HelloWorld")

    .addModifiers(Modifier.PUBLIC)

    .build();

7.枚举

TypeSpec helloWorld = TypeSpec.enumBuilder("Roshambo")

    .addModifiers(Modifier.PUBLIC)

    .addEnumConstant("ROCK")

    .addEnumConstant("SCISSORS")

    .addEnumConstant("PAPER")

    .build();

参考文章
http://blog.csdn.net/crazy1235/article/details/51876192
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: