赞
踩
本文主要介绍利用jdk自带的tools.jar库生成常见java语法。使用场景主要是编译时注解,如lombok等,大致原理为在编译的时候插入相应的语句,体现在class文件上会多出相应语句。
以下内容主要是提炼了一下相关的方法,方便用时参考。本文基于jdk1.8都测试成功。
ps:
也在jdk17中调试过,但是未到测试那一步就有一系列其他报错,之后因为时间原因忙其他东西去了。
示例:
public void test() {
// 生成int类型变量myVariable
int myVariable;
}
代码如下:
private JCVariableDecl createStatement() {
JCModifiers modifiers = treeMaker.Modifiers(0);
Name myVariableName = names.fromString("myVariable");
JCExpression variableType = treeMaker.TypeIdent(TypeTag.INT);
return treeMaker.VarDef(modifiers, myVariableName, variableType, null);
}
示例:
public void test() {
// 生成StringBuilder变量
StringBuilder jsonBuilder = new StringBuilder();
}
代码如下:
private JCVariableDecl createStatement() {
JCModifiers variableModifiers = treeMaker.Modifiers(0);
JCExpression variableType = treeMaker.Ident(names.fromString("StringBuilder"));
Name variableName = names.fromString("stringBuilder");
return treeMaker.VarDef(variableModifiers, variableName, variableType, treeMaker.NewClass(null, List.nil(), variableType, List.nil(), null));
}
示例:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
代码:
/** * 创建简单日期格式声明 * * @return {@link JCStatement} */ private JCStatement createSimpleDateFormatStatement() { return treeMaker.VarDef( treeMaker.Modifiers(0), names.fromString("simpleDateFormat"), treeMaker.Ident(names.fromString("SimpleDateFormat")), treeMaker.NewClass( null, List.nil(), treeMaker.Ident(names.fromString("SimpleDateFormat")), List.of(treeMaker.Literal("yyyy-MM-dd HH:mm:ss")), null ) ); }
示例:
String myVariable = "aa";
代码:
/**
* 创建语句
* String myVariable = "aa";
*
* @return {@link JCVariableDecl}
*/
private JCVariableDecl createStringStatement() {
JCModifiers modifiers = treeMaker.Modifiers(0);
Name myVariableName = names.fromString("myVariable");
JCExpression variableType = treeMaker.Ident(names.fromString("String"));
JCExpression assignmentExpr = treeMaker.Literal(TypeTag.CLASS, "aa");
return treeMaker.VarDef(modifiers, myVariableName, variableType, assignmentExpr);
}
注意:调用变量的方法,必须先定义变量,不然编译报错
示例:
String myVariable1 = simpleDateFormat.format("value");
代码:
/** * 创建语句 * String myVariable1 = sdf.format(xxxx);; * * @return {@link JCVariableDecl} */ private JCVariableDecl createVarToVarMethodStatement() { JCModifiers modifiers = treeMaker.Modifiers(0); Name myVariableName = names.fromString("myVariable1"); JCExpression variableType = treeMaker.Ident(names.fromString("String")); // 创建simpleDateFormat.format(date) JCExpression receiver = treeMaker.Select( treeMaker.Ident(names.fromString("simpleDateFormat")), names.fromString("format") ); JCExpression arg = treeMaker.Literal("value"); JCMethodInvocation printInvocation = treeMaker.Apply( List.nil(), receiver, List.of(arg) ); return treeMaker.VarDef(modifiers, myVariableName, variableType, printInvocation); }
示例:
public void test() {
String str = null;
// 给str赋值
str = "aa";
}
代码如下:
public JCStatement createStringStatement() {
Name variableName = names.fromString("str");
JCExpression assignmentExpr = treeMaker.Literal(TypeTag.CLASS, "aa");
return treeMaker.Exec(treeMaker.Assign(treeMaker.Ident(variableName), assignmentExpr));
}
示例:
public class Test {
private int num;
private int value;
public Test(int num, int value) {
this.num = num;
this.value = value;
}
}
代码如下:
private JCMethodDecl makeConstructorMethodDecl() { // Generate constructor parameters JCVariableDecl parameter1 = treeMaker.VarDef( treeMaker.Modifiers(Flags.PARAMETER), names.fromString("num"), treeMaker.TypeIdent(TypeTag.INT), null ); JCVariableDecl parameter2 = treeMaker.VarDef( treeMaker.Modifiers(Flags.PARAMETER), names.fromString("value"), treeMaker.TypeIdent(TypeTag.INT), null ); List<JCVariableDecl> parameters = List.of(parameter1, parameter2); // Generate constructor body JCBlock body = treeMaker.Block(0, List.nil()); // Generate field assignments JCExpressionStatement assignNum = treeMaker.Exec( treeMaker.Assign( treeMaker.Select(treeMaker.Ident(names.fromString("this")), names.fromString("num")), treeMaker.Ident(parameter1.name) ) ); JCExpressionStatement assignValue = treeMaker.Exec( treeMaker.Assign( treeMaker.Select(treeMaker.Ident(names.fromString("this")), names.fromString("value")), treeMaker.Ident(parameter2.name) ) ); body.stats = body.stats.append(assignNum).append(assignValue); // Generate constructor declaration JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC); return treeMaker.MethodDef( modifiers, names.fromString("<init>"), null, List.nil(), parameters, List.nil(), body, null ); }
示例:
public class Test {
private int num;
private int value;
public Test() {
}
public Test(int num, int value) {
this.num = num;
this.value = value;
}
}
代码如下:
private JCMethodDecl makeNoneConstructorMethodDecl() {
JCBlock body = treeMaker.Block(0, List.nil());
// Generate constructor declaration
JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC);
return treeMaker.MethodDef(
modifiers,
names.fromString("<init>"),
null,
List.nil(),
List.nil(),
List.nil(),
body,
null
);
}
public JCStatement createSysOutStatement() {
Name variableName = names.fromString("str");
JCExpression printlnExpr = treeMaker.Ident(names.fromString("System"));
printlnExpr = treeMaker.Select(printlnExpr, names.fromString("out"));
printlnExpr = treeMaker.Select(printlnExpr, names.fromString("println"));
JCMethodInvocation printlnInvocation = treeMaker.Apply(List.nil(), printlnExpr, List.of(treeMaker.Ident(variableName)));
return treeMaker.Exec(printlnInvocation);
}
private JCExpressionStatement createConstantAppendStatement(String date) {
// 创建dateFormart.format(date)
JCExpression receiver = treeMaker.Select(
treeMaker.Ident(names.fromString("dateFormart")),
names.fromString("format")
);
JCExpression arg = treeMaker.Literal(value);
JCMethodInvocation printInvocation = treeMaker.Apply(
List.nil(),
receiver,
List.of(arg)
);
// 创建语句
return treeMaker.Exec(printInvocation);
}
private JCExpressionStatement createConstantAppendStatement() {
// 创建user.getName()
JCExpression receiver = treeMaker.Select(
treeMaker.Ident(names.fromString("user")),
names.fromString("getName")
);
JCMethodInvocation printInvocation = treeMaker.Apply(
List.nil(),
receiver,
List.nil()
);
// 创建语句
return treeMaker.Exec(printInvocation);
}
private JCExpressionStatement createVarAppendStatement(String date) {
// 创建dateFormart.format(date)
JCExpression receiver = treeMaker.Select(
treeMaker.Ident(names.fromString("dateFormart")),
names.fromString("format")
);
JCExpression arg = treeMaker.Ident(names.fromString(value));
JCMethodInvocation printInvocation = treeMaker.Apply(
List.nil(),
receiver,
List.of(arg)
);
// 创建语句
return treeMaker.Exec(printInvocation);
}
示例:
public void test() {
if (this.name != null) {
System.out.println("hello world");
}
}
代码如下:
public JCStatement createSysOutStatement(String value) { JCExpression printlnExpr = treeMaker.Ident(names.fromString("System")); printlnExpr = treeMaker.Select(printlnExpr, names.fromString("out")); printlnExpr = treeMaker.Select(printlnExpr, names.fromString("println")); JCMethodInvocation printlnInvocation = treeMaker.Apply(List.nil(), printlnExpr, List.of(treeMaker.Literal(value))); return treeMaker.Exec(printlnInvocation); } private JCStatement createFieldIfNullStatement() { JCTree.JCExpression condition = treeMaker.Binary( JCTree.Tag.NE, treeMaker.Ident(names.fromString("name")), treeMaker.Literal(TypeTag.BOT, null) ); ListBuffer<JCTree.JCStatement> statements = new ListBuffer<>(); JCStatement sysOutStatement = createSysOutStatement("hello world"); statements.append(sysOutStatement); return treeMaker.If(condition, treeMaker.Block(0, statements.toList()), null); }
示例:
public void test() {
if (this.name != null) {
System.out.println("hello world");
} else {
System.out.println("hello java");
}
}
代码如下:
private JCStatement createFieldIfNullStatement() {
JCTree.JCExpression condition = treeMaker.Binary(
JCTree.Tag.NE,
treeMaker.Ident(names.fromString("name")),
treeMaker.Literal(TypeTag.BOT, null)
);
ListBuffer<JCTree.JCStatement> statements = new ListBuffer<>();
JCStatement sysOutStatement = createSysOutStatement("hello world");
statements.append(sysOutStatement);
ListBuffer<JCTree.JCStatement> elseStatements = new ListBuffer<>();
JCStatement elseStatement = createSysOutStatement("hello java");
elseStatements.append(elseStatement);
return treeMaker.If(condition, treeMaker.Block(0, statements.toList()), treeMaker.Block(0, elseStatements.toList()));
}
/**
* 创建和返回语句块.</br>
* <pem>return jsonBuilder.toString();</pem>
*
* @return {@link JCStatement}
*/
private JCStatement createBlockWithReturnStatement() {
return treeMaker.Return(treeMaker.Apply(null, treeMaker.Select(treeMaker.Ident(names.fromString("jsonBuilder")), names.fromString("toString")), List.nil()));
}
示例:
public void onParamMethod() {
}
代码如下:
private JCTree.JCMethodDecl makeNoParamMethodDecl() { // Generate method modifiers JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC); // Generate method parameters List<JCVariableDecl> parameters = List.nil(); // Generate method return type JCExpression returnType = treeMaker.TypeIdent(TypeTag.VOID); return treeMaker.MethodDef( modifiers, names.fromString("onParamMethod"), returnType, List.nil(), parameters, List.nil(), treeMaker.Block(0, List.nil()), null ); }
示例:
public void paramMethod(String param) {
}
代码如下:
private JCTree.JCMethodDecl makeMethodDecl() { // Generate method parameters JCVariableDecl parameter = treeMaker.VarDef( treeMaker.Modifiers(Flags.PARAMETER), names.fromString("param"), treeMaker.Ident(names.fromString("String")), null ); List<JCVariableDecl> parameters = List.of(parameter); // Generate method body JCBlock body = treeMaker.Block(0, List.nil()); // Generate method declaration JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC); return treeMaker.MethodDef( modifiers, names.fromString("paramMethod"), treeMaker.TypeIdent(TypeTag.VOID), List.nil(), parameters, List.nil(), body, null ); }
示例:
public String paramMethod(String param) {
return "hello world";
}
代码如下:
private JCTree.JCMethodDecl makeMethodDecl() { // Generate method parameters JCVariableDecl parameter = treeMaker.VarDef( treeMaker.Modifiers(Flags.PARAMETER), names.fromString("param"), treeMaker.Ident(names.fromString("String")), null ); List<JCVariableDecl> parameters = List.of(parameter); // Generate method body JCBlock body = treeMaker.Block(0, List.nil()); JCReturn returnStatement = treeMaker.Return(treeMaker.Literal("hello world")); body.stats = body.stats.append(returnStatement); // Generate method declaration JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC); return treeMaker.MethodDef( modifiers, names.fromString("paramMethod"), treeMaker.Ident(names.fromString("String")), List.nil(), parameters, List.nil(), body, null ); }
示例:
public String dateToString(Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return simpleDateFormat.format(date);
}
代码如下:
private JCTree.JCMethodDecl makeMethodDecl() { // Generate method parameters JCVariableDecl parameter = treeMaker.VarDef( treeMaker.Modifiers(Flags.PARAMETER), names.fromString("date"), treeMaker.Ident(names.fromString("Date")), null ); List<JCVariableDecl> parameters = List.of(parameter); // Generate method body ListBuffer<JCStatement> statements = new ListBuffer<>(); // Generate SimpleDateFormat declaration JCVariableDecl sdfDeclaration = treeMaker.VarDef( treeMaker.Modifiers(0), names.fromString("simpleDateFormat"), treeMaker.Ident(names.fromString("SimpleDateFormat")), treeMaker.NewClass( null, List.nil(), treeMaker.Ident(names.fromString("SimpleDateFormat")), List.of(treeMaker.Literal("yyyy-MM-dd HH:mm:ss")), null ) ); statements.append(sdfDeclaration); // Generate return statement JCMethodInvocation formatInvocation = treeMaker.Apply(null, treeMaker.Select(treeMaker.Ident(names.fromString("simpleDateFormat")), names.fromString("format")), List.of(treeMaker.Ident(names.fromString("date")))); JCReturn returnStatement = treeMaker.Return(formatInvocation); statements.append(returnStatement); JCBlock body = treeMaker.Block(0, statements.toList()); JCModifiers modifiers = treeMaker.Modifiers(Flags.PUBLIC); return treeMaker.MethodDef( modifiers, names.fromString("dateToString"), treeMaker.Ident(names.fromString("String")), List.nil(), parameters, List.nil(), body, null ); }
可以参考上面的例子
public JCStatement createSysOutStatement(String value) {
JCExpression printlnExpr = treeMaker.Ident(names.fromString("System"));
printlnExpr = treeMaker.Select(printlnExpr, names.fromString("out"));
printlnExpr = treeMaker.Select(printlnExpr, names.fromString("println"));
JCMethodInvocation printlnInvocation = treeMaker.Apply(List.nil(), printlnExpr, List.of(treeMaker.Literal(value)));
return treeMaker.Exec(printlnInvocation);
}
private void addImport(Element e) { TreePath treePath = this.trees.getPath(e); JCTree.JCCompilationUnit jct = (JCTree.JCCompilationUnit) treePath.getCompilationUnit(); java.util.List<JCTree> trees = new ArrayList(); trees.addAll(jct.defs); java.util.List<JCTree> sourceImportList = new ArrayList(); trees.forEach((tree) -> { if (tree.getKind().equals(Tree.Kind.IMPORT)) { sourceImportList.add(tree); } }); java.util.List<JCTree.JCImport> needImportList = new ArrayList(); JCTree.JCImport anImport = this.treeMaker.Import(this.memberAccess("java.util.Date"), false); needImportList.add(anImport); anImport = this.treeMaker.Import(this.memberAccess("java.text.SimpleDateFormat"), false); needImportList.add(anImport); for (int i = 0; i < needImportList.size(); ++i) { boolean importExist = false; for (int j = 0; j < sourceImportList.size(); ++j) { if ((sourceImportList.get(j)).toString().equals((needImportList.get(i)).toString())) { importExist = true; } } if (!importExist) { trees.add(0, needImportList.get(i)); } } jct.defs = List.from(trees); } private JCTree.JCExpression memberAccess(String components) { String[] componentArray = components.split("\\."); JCTree.JCExpression expr = this.treeMaker.Ident(names.fromString(componentArray[0])); for (int i = 1; i < componentArray.length; ++i) { expr = this.treeMaker.Select(expr, names.fromString(componentArray[i])); } return expr; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。