前言
环境准备
添加JavaParser依赖
<dependency>
<groupId>com.github.javaparser</groupId>
<artifactId>javaparser-core</artifactId>
<version>3.25.4</version>
</dependency>
第一个AST解析程序
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
public class FirstASTDemo {
public static void main(String[] args) {
String code =
\"public class HelloWorld {n\" +
\" public void sayHello() {n\" +
\" System.out.println(\"Hello AST!\");n\" +
\" }n\" +
\"}\";
// 解析代码为AST
CompilationUnit cu = StaticJavaParser.parse(code);
// 查看AST结构
System.out.println(\"=== AST结构 ===\");
System.out.println(cu.toString());
}
}
运行这个程序,你会看到完整的AST结构输出。
AST遍历:Visitor模式
理解Visitor设计模式
在AST处理中,Visitor模式让我们能够\”访问\”每个节点而不修改AST结构。
// 类比:博物馆参观者
public interface ASTVisitor {
void visit(ClassDeclaration node); // 参观\"类展区\"
void visit(MethodDeclaration node); // 参观\"方法展区\"
void visit(FieldDeclaration node); // 参观\"字段展区\"
// ... 其他展区
}
实现自定义Visitor
public class MethodCounter extends VoidVisitorAdapter {
private int methodCount = 0;
@Override
public void visit(MethodDeclaration md, Void arg) {
methodCount++;
System.out.println(\"发现方法: \" + md.getName() +
\" (参数: \" + md.getParameters().size() + \")\");
super.visit(md, arg);
}
public int getMethodCount() {
return methodCount;
}
}
使用这个Visitor:
public class VisitorDemo {
public static void main(String[] args) {
String code =
\"public class Calculator {n\" +
\" public int add(int a, int b) { return a + b; }n\" +
\" public int multiply(int a, int b) { return a * b; }n\" +
\"}\";
CompilationUnit cu = StaticJavaParser.parse(code);
MethodCounter counter = new MethodCounter();
counter.visit(cu, null);
System.out.println(\"总方法数: \" + counter.getMethodCount());
}
}
输出:
发现方法: add (参数: 2)
发现方法: multiply (参数: 2)
总方法数: 2
常用Visitor场景
收集所有字段信息
public class FieldCollector extends VoidVisitorAdapter {
private List fields = new ArrayList();
@Override
public void visit(FieldDeclaration fd, Void arg) {
fd.getVariables().forEach(variable -> {
String fieldInfo = String.format(\"%s %s %s\",
fd.getModifiers(), // 访问修饰符
fd.getElementType(), // 字段类型
variable.getName() // 字段名
);
fields.add(fieldInfo);
});
super.visit(fd, arg);
}
public List getFields() {
return fields;
}
}
查找特定方法调用
public class MethodCallFinder extends VoidVisitorAdapter {
private String targetMethod;
private List calls = new ArrayList();
public MethodCallFinder(String targetMethod) {
this.targetMethod = targetMethod;
}
@Override
public void visit(MethodCallExpr n, Void arg) {
if (n.getNameAsString().equals(targetMethod)) {
calls.add(\"在位置: \" + n.getRange().map(r -> r.begin.line).orElse(-1));
}
super.visit(n, arg);
}
}
AST结构可视化:理解AST树
递归打印AST树
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.Node;
public class ASTTreeViewer {
public static void main(String[] args) {
String code =
\"public class Calculator {n\" +
\" private int value;n\" +
\" n\" +
\" public int add(int a, int b) {n\" +
\" return a + b + value;n\" +
\" }n\" +
\"}\";
CompilationUnit cu = StaticJavaParser.parse(code);
System.out.println(\"=== AST树状结构 ===\");
printASTTree(cu, 0);
}
/**
* 递归打印AST树结构
* @param node 当前节点
* @param depth 当前深度(用于缩进)
*/
public static void printASTTree(Node node, int depth) {
String indent = \" \".repeat(depth); // 根据深度生成缩进
String nodeType = node.getClass().getSimpleName();
// 简化的节点内容(避免输出过长)
String content = getNodeSummary(node);
System.out.println(indent + nodeType + \": \" + content);
// 递归打印所有子节点
for (Node child : node.getChildNodes()) {
printASTTree(child, depth + 1);
}
}
/**
* 获取节点的简化信息
*/
private static String getNodeSummary(Node node) {
String fullString = node.toString().split(\"n\")[0]; // 取第一行
if (fullString.length() > 50) {
return fullString.substring(0, 47) + \"...\";
}
return fullString;
}
}
运行结果示例
=== AST树状结构 ===
CompilationUnit: public class Calculator {
ClassOrInterfaceDeclaration: public class Calculator {
Modifier: public
SimpleName: Calculator
FieldDeclaration: private int value;
Modifier: private
VariableDeclarator: value
PrimitiveType: int
SimpleName: value
MethodDeclaration: public int add(int a, int b) {
Modifier: public
SimpleName: add
Parameter: int a
PrimitiveType: int
SimpleName: a
Parameter: int b
PrimitiveType: int
SimpleName: b
PrimitiveType: int
BlockStmt: {
ReturnStmt: return a + b + value;
BinaryExpr: a + b + value
BinaryExpr: a + b
NameExpr: a
SimpleName: a
NameExpr: b
SimpleName: b
NameExpr: value
SimpleName: value
AST树结构解析
树的层次关系
CompilationUnit (根节点 - 整个文件)
└── ClassOrInterfaceDeclaration (类声明)
├── Modifier (修饰符: public)
├── SimpleName (类名: Calculator)
├── FieldDeclaration (字段声明)
│ ├── Modifier (修饰符: private)
│ └── VariableDeclarator (变量声明器)
│ └── SimpleName (字段名: value)
└── MethodDeclaration (方法声明)
├── Modifier (修饰符: public)
├── SimpleName (方法名: add)
├── Parameter (参数)
│ ├── PrimitiveType (类型: int)
│ └── SimpleName (参数名: a)
├── BlockStmt (方法体)
│ └── ReturnStmt (返回语句)
│ └── BinaryExpr (二元表达式: a + b + value)
│ ├── BinaryExpr (子表达式: a + b)
│ │ ├── NameExpr (变量a)
│ │ └── NameExpr (变量b)
│ └── NameExpr (变量value)
关键节点类型说明
| 节点类型 | 说明 | 示例 |
|---|---|---|
CompilationUnit |
整个编译单元 | 整个.java文件 |
ClassOrInterfaceDeclaration |
类或接口声明 | class Calculator |
MethodDeclaration |
方法声明 | public int add(...) |
FieldDeclaration |
字段声明 | private int value |
VariableDeclarator |
变量声明器 | value (字段名) |
BlockStmt |
代码块 | { ... } |
ReturnStmt |
返回语句 | return a + b |
BinaryExpr |
二元表达式 | a + b, x > y |
NameExpr |
名称表达式 | a, b, value |
AST修改:实现代码自动生成
为类添加字段
public class ClassModifier {
public static void addField(CompilationUnit cu,
String fieldName,
String fieldType) {
// 为 user 类添加字段
cu.getClassByName(\"User\").ifPresent(clazz -> {
// 构建字段代码
String fieldCode = \"private \" + fieldType + \" \" + fieldName + \";\";
// 解析为AST节点并添加
var field = StaticJavaParser.parseBodyDeclaration(fieldCode);
clazz.addMember(field);
System.out.println(\"成功添加字段: \" + fieldName);
});
}
}
自动生成Getter方法
public class GetterGenerator extends VoidVisitorAdapter {
@Override
public void visit(ClassOrInterfaceDeclaration cid, Void arg) {
// 为每个字段生成getter
cid.getFields().forEach(field -> {
field.getVariables().forEach(variable -> {
String fieldName = variable.getNameAsString();
String fieldType = field.getElementType().asString();
generateGetter(cid, fieldName, fieldType);
});
});
super.visit(cid, arg);
}
private void generateGetter(ClassOrInterfaceDeclaration clazz,
String fieldName, String fieldType) {
String getterName = \"get\" + capitalize(fieldName);
String getterCode = String.format(
\"public %s %s() { return this.%s; }\",
fieldType, getterName, fieldName
);
try {
var getter = StaticJavaParser.parseBodyDeclaration(getterCode);
clazz.addMember(getter);
System.out.println(\"生成Getter: \" + getterName);
} catch (Exception e) {
System.err.println(\"生成Getter失败: \" + e.getMessage());
}
}
private String capitalize(String str) {
return str.substring(0, 1).toUpperCase() + str.substring(1);
}
}



还没有评论呢,快来抢沙发~