编译期注解之JavaPoet
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译期注解之JavaPoet
0x01 简单使用
使用之前要先引入这个库
compile 'com.squareup:javapoet:1.7.0'
javapoet是用来生成代码的,需要借助
常用类
使用javapoet前需要了解4个常用类
MethodSpec 代表一个构造函数或方法声明。
TypeSpec 代表一个类,接口,或者枚举声明。
FieldSpec 代表一个成员变量,一个字段声明。
JavaFile包含一个顶级类的Java文件。
国际惯例先自动生成一个helloWorld类
定义一个编译期注解
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface clazz_hello {
String value();
}
然后看下helloworld的注解处理器
@AutoService(Processor.class)
public class HelloWorldProcess extends AbstractProcessor {
private Filer filer;
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
filer = processingEnv.getFiler();
}
@Override
public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
for (TypeElement element : annotations) {
if
(element.getQualifiedName().toString().equals(clazz_hello.class.getCanonicalName())) {
MethodSpec main = MethodSpec.methodBuilder("main")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(void.class)
.addParameter(String[].class, "args")
.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
.build();
TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addMethod(main)
.build();
try {
JavaFile javaFile = JavaFile.builder("com.xsf", helloWorld)
.addFileComment(" This codes are generated automatically. Do not modify!")
.build();
javaFile.writeTo(filer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
return true;
}
@Override
public Set
Set
annotations.add(clazz_hello.class.getCanonicalName());
return annotations;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return testSupported();
}
}
这样就会在app-build-source-apt-debug-com.xsf文件夹下生成这个文件
0x02 使用进阶
方法&控制流:
添加方法addcode 和addstatement
对与无需类引入的极简代码可以直接使用addCode
MethodSpec main = MethodSpec.methodBuilder("main")
.addCode(""
+ "int total = 0;\n"
+ "for (int i = 0; i < 10; i++) {\n"
+ " total += i;\n"
+ "}\n")
.build();
生成的是
void main() {
int total = 0;
for (int i = 0; i < 10; i++) {
total += i;
}
}
要是需要import的方法,如上面的.addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!") 就需要使用.addStatement来声明
更优雅的流控制
beginControlFlow 流开启
addStatement 处理语句
endControlFlow()流结束
如上面的用流改写就是
MethodSpec main = MethodSpec.methodBuilder("main")
.addStatement("int total = 0")
.beginControlFlow("for (int i = 0; i < 10; i++)")
.addStatement("total += i")
.endControlFlow()
.build();
占位符
javapoet里面提供了占位符来帮助我们更好地生成代码
$L 字面常量(Literals)
private MethodSpec computeRange(String name, int from, int to, String op) {
return MethodSpec.methodBuilder(name)
.returns(int.class)