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是用來新建函數(shù)的圃酵,通過methodBuilder取函數(shù)名并通過addCode來添加代碼,TypeSpec則是用來生成類嘿歌,通過classBuilder來創(chuàng)建和去類名掸掏,通過addModifiers來規(guī)定類的屬性,然后通過addMethod添加函數(shù)搅幅。最后是通過JavaFile來生成相應包下的java文件阅束,指定了包名和類呼胚。
后面我會重點說MethodSpec如何用茄唐,就不貼完整代碼了
2.引用自己給參數(shù)
以上代碼還有另一種方法生成,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();
還能給生成有參數(shù)的函數(shù)
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();
}
還有另一種生成有參數(shù)的函數(shù),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.*;
還有生成的函數(shù)引用自己生成的函數(shù)
通過$N來引用 hexDigit()方法作為一個參數(shù):
addStatement("result[1] = $N(1)", hexDigit)
4.構造函數(shù)
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