javapoet使用

xiaoxiao2021-02-28  23

javapoet简介

javapoet是一个用于生成.java源文件的Java API。相关的还有javaWriter是javapoet的一个分支,ASM是一个java字节码操纵框架,它能被用来动态生成类或者增强既有类的功能。ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。javapoet常用来做编译时java文件生成,在butterknife和dagger中使用。

javapoet中API的使用

1.我们动态生成类使用TypeSpec.classBuilder()方法,在classBuilder方法中参数类型为String或者ClassName,就是生成class类的名称,ClassName是JavaPoet中定义的一个对象,可以通过ClassName.get()获取,在这个里面可以传入包名和类名组成一个全路径名称,ClassName.get(“www.hikvision.com”,TestBuilder)组成一个www.hikvision.com.TestBuilder全路径名。

TypeSpec build = TypeSpec.classBuilder("TestBuilder") .build(); String path = Main.class.getResource("/").getPath(); File file = new File(path); JavaFile.builder("www.hikvision.com",build).build().writeTo(file);

# 在上面classBuilder中是类的名称,JavaFile.builder(“www.hikvision.com”,build).build().writeTo(file);”www.hikvision.com”是包名。生成文件如下

package www.hikvision.com; class TestBuilder { }

2.可以通过修饰符来修饰一个类,Modifier是修饰符枚举,里面定义了 PUBLIC,PROTECTED,PRIVATE,ABSTRACT,DEFAULT,STATIC,FINAL, TRANSIENT,VOLATILE,SYNCHRONIZED,NATIVE,STRICTFP;12个修饰符类addModifiers()方法调用

TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .build();

3.在生成类中添加字段,通过FieldSpec.builder()来生成字段,在builder定义字段的类型,名称和修饰符,再通过addFiled()添加到类中

TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .addField(FieldSpec.builder(TypeName.BOOLEAN,"isOpen",Modifier.PROTECTED).build()) .build();

4.构造方法的添加,通过addMethod()方法添加一个MethodSpec对象,可以通过MethodSpec.constructorBuilder()生成一个构造方法,也可生通过MethodSpec.methodBuilder()成一个普通方法,记得在生成构造方法时通过修饰符addModifiers()修饰构造方法

TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC)

.addMethod(MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).build()) .build();

5.生成类中使用泛型,使用addTypeVariable方法,可以通过添加TypeVariableName来设置类的泛型 TypeVariableName typeVariableName=TypeVariableName.get(“T”);

TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .addTypeVariable(typeVariableName) .build();

6.泛型约束例如,还是可以通过TypeVariableName来设置

TypeVariableName typeVariableName=TypeVariableName.get("T",TypeName.get(Main.class)); TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .addTypeVariable(typeVariableName) .build();

7.实现接口通过addSuperinterface()方法实现接口实现

TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .addSuperinterface(ITest.class) .build();

8.继承类superclass()

TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .superclass(Test.class) .build();

9.接口泛型约束 public class A implement B{}这种在接口上面添加泛型约束,通过addSuperinterface()方法和ParameterizedTypeName结合使用,通过ParameterizedTypeName包裹接口类和泛型来实现

ParameterizedTypeName parameterizedTypeName=ParameterizedTypeName.get(ITest.class,Main.class); TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .addSuperinterface(parameterizedTypeName) .build();

10.普通方法添加通过addMethod方法,使用MethodSpec.methodBuilder()添加方法

MethodSpec testMethod = MethodSpec.methodBuilder("test") .addModifiers(Modifier.PUBLIC) .build(); TypeSpec build = TypeSpec.classBuilder("TestBuilder") .addModifiers(Modifier.ABSTRACT,Modifier.PUBLIC,Modifier.STATIC) .addMethod(testMethod) .build();

11.返回值添加是MethodSpec.returns()

MethodSpec testMethod = MethodSpec.methodBuilder("test") .addModifiers(Modifier.PUBLIC) .returns(Main.class) .build();

12.方法参数添加MethodSpec.addParameter

CodeBlock codeBlock=CodeBlock.builder() .add("T temp=t;\n") .build(); MethodSpec testMethod = MethodSpec.methodBuilder("test") .addModifiers(Modifier.PUBLIC) .addParameter(typeVariableName,"t") .build();

13.Map泛型使用

Map<String, Class<? extends IRouteGroup>> ParameterizedTypeName inputMapTypeOfRoot = ParameterizedTypeName.get( ClassName.get(Map.class), ClassName.get(String.class), ParameterizedTypeName.get( ClassName.get(Class.class), WildcardTypeName.subtypeOf(ClassName.get(type_IRouteGroup)) ) );

14.代码块$L使用

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

代码块添加有两种方法addCode()和addStatement()两种方式,在addCode中可以创建一个CodeBlock代码块添加代码,在生成代码块是可以使用format对代码进行替换,在javapoet中主要用 S, S , T, L L , N四种, T T 主 要 是 替 换 相 关 的 类 , S主要替换字符串, L L 替 换 参 数 , N替换名字,一般调用方法可以通过$N替换。https://github.com/square/javapoet这个是javapoet在github托管网址,有javapoet基础用法,关于泛型使用没有讲解,可以学习butterknife中泛型使用https://github.com/JakeWharton/butterknife,也可以看下我GitHub关于编译时注解demo,https://github.com/starsquare/star_sky里面有相关泛型的引用。

CodeBlock codeBlock=CodeBlock.builder() .add("T temp=t;\n") .build(); MethodSpec testMethod = MethodSpec.methodBuilder("test") .addModifiers(Modifier.PUBLIC) .addCode(codeBlock) .addStatement("$T m=new $T()",Main.class,Main.class) .build();
转载请注明原文地址: https://www.6miu.com/read-2250259.html

最新回复(0)