动态生成java代码???java代码不就是一个后缀名为.java的txt文档吗?仔细想了下,如果要生成这样的代码的确挺麻烦,你要考虑导包的问题,以及复杂的语法
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)//添加类的方法,也就是上面生成的MethodSpec对象 .build();
JavaFile介绍
JavaFile javaFile = JavaFile.builder("com.example.helloworld", helloWorld)//定义生成的包名,和类 .build(); javaFile.writeTo(System.out);//输出路径,可以收一个file地址
最终生成
package com.example.helloworld; public final class HelloWorld { public static void main(String[] args) { System.out.println("Hello, JavaPoet!"); } }
MethodSpec hexDigit = MethodSpec.methodBuilder("hexDigit") .addParameter(int.class, "i") .returns(char.class) .addStatement("return (char) (i < 10 ? i + '0' : i - 10 + 'a')") .build(); MethodSpec byteToHex = MethodSpec.methodBuilder("byteToHex") .addParameter(int.class, "b") .returns(String.class) .addStatement("char[] result = new char[2]") .addStatement("result[0] = $N((b >>> 4) & 0xf)", hexDigit) .addStatement("result[1] = $N(b & 0xf)", hexDigit) .addStatement("return new String(result)") .build();
//生成的代码
public String byteToHex(int b) { char[] result = new char[2]; result[0] = hexDigit((b >>> 4) & 0xf); result[1] = hexDigit(b & 0xf); return new String(result); } public char hexDigit(int i) { return (char) (i < 10 ? i + '0' : i - 10 + 'a'); }
.beginControlFlow("while(value<$L)", 10)//循环开始
.addStatement("int value2=$L", 10)
.endControlFlow()
while(value<10) {
int value2=10;
}
MethodSpec main = MethodSpec.methodBuilder("main") .addCode("" + "int total = 0;\n" + "for (int i = 0; i < 10; i++) {\n" + " total += i;\n" + "}\n") .build();
ClassName hoverboard = ClassName.get("com.mattel", "Hoverboard");//包名和类名 MethodSpec today = MethodSpec.methodBuilder("tomorrow") .returns(hoverboard) .addStatement("return new $T()", hoverboard) .build();
自己写的Demo
public class Demo { public static void main(String args[]) { try { /** * $T 传入一个类型,可以使class或者ClassName对象,这个会自动帮你导入包 * $S 替换一个字符串,会用"引号" * $L 就是占位一个值,一个变量 * $N 就是占位一个方法 可以传入一个MethodSpec对象 */ ClassName persionClassName = ClassName.get("com.awen.demo.bean", "Persion");//这种找到的形式都和class形式一样可以用 MethodSpec main = MethodSpec.methodBuilder("main") .addModifiers(Modifier.STATIC, Modifier.PUBLIC) .addParameter(String[].class, "args") //添加参数 .addParameter(persionClassName, "myPersion")//添加参数 .returns(persionClassName) .addStatement("int value=$L", 10) .addStatement("$T obj=new $T()", persionClassName, Persion.class) .addStatement("$T.out.println($S)", System.class, "来吧创建一个类来玩玩吧!") .beginControlFlow("while(value<$L)", 10)//循环开始 .addStatement("int value2=$L", 10) .endControlFlow() .addStatement("return new $T()", Class.forName("com.awen.demo.bean.Persion")) .build(); //创建变量 FieldSpec fieldSpec = FieldSpec.builder(String.class, "VALUE") .addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL) .initializer("$S","AAA").build(); TypeSpec classSpec = TypeSpec.classBuilder("Test") .addModifiers(Modifier.PUBLIC, Modifier.FINAL) .addField(String.class, "name", Modifier.PUBLIC) .addField(fieldSpec) .addMethod(main) // .addType(classSpec2)//追加一个内部类 .build(); JavaFile build = JavaFile.builder("com.awen.demo", classSpec).build(); build.writeTo(new File("src/main/java")); } catch (Exception e) { System.out.println("发生错误:" + e.getLocalizedMessage()); } } }
生成代码
public final class Test { public static final String VALUE = "AAA"; public String name; public static Persion main(String[] args, Persion myPersion) { int value=10; Persion obj=new Persion(); System.out.println("来吧创建一个类来玩玩吧!"); while(value<10) { int value2=10; } return new Persion(); } }
大家其实大家或多或少都其实用过这玩意,只是大家用了别人的罢了,例如ButterKnife,注入框架,为何不用一个注解就不用在写findViewById了?其实无论本质还是要find的,但是为何不需要了呢?就是在编译前期自动帮你生成了部分代码!
还有greendao,其实这个你也发现了,在你build的时候,也会生成一部分代码?怎么生成的呢?所以说这个在插件开发中还是用处很大的,还要继续学习,这个面向的java层代码的生成
通过定义plugin插件,可以用这个在编译前期生成部分java代码,然后在transform+asm库对class文件进行修改,插入并调用自动生成的java代码,埋点吧!很想学这个玩着个,继续努力