
正如摘要所说,在使用 JavaParser 解析 Java 代码时,提取类或接口声明中的类型引用时,可能会遇到完全限定名 (FQ) 被错误地分解成多个部分的问题。例如,解析 java.lang.String 时,可能会得到 java.lang.String、java.lang 和 java 三个结果,而不是期望的单个 java.lang.String。这会给后续处理带来不便。本文将介绍如何使用递归方法准确地提取所需的类型名称,并避免这些不必要的中间结果。
问题分析
在使用 JavaParser 时,如果直接使用 stream().filter(ClassOrInterfaceType.class::isInstance) 的方式提取类型,JavaParser 会将完全限定名 (FQ) 分解为多个部分。这是因为 JavaParser 会遍历类型名称的每个组成部分,并将它们都识别为 ClassOrInterfaceType。
解决方案:递归方法
为了解决这个问题,我们可以使用递归方法来提取类型名称。以下是一个示例代码:
import com.github.javaparser.StaticJavaParser;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
public class TypeExtraction {
public static void main(String[] args) {
String s = "class Foo extends java.lang.String {}";
CompilationUnit cu = StaticJavaParser.parse(s);
cu.findAll(ClassOrInterfaceDeclaration.class).forEach(cid -> {
System.out.println("Class Name: " + cid.getNameAsString());
cid.getExtendedTypes().forEach(extType -> System.out.println("Extended Type: " + extType.getNameAsString()));
});
}
}代码解释:
立即学习“Java免费学习笔记(深入)”;
- 导入必要的类: 导入 StaticJavaParser、CompilationUnit 和 ClassOrInterfaceDeclaration 等 JavaParser 相关的类。
- 解析 Java 代码: 使用 StaticJavaParser.parse(s) 解析包含类声明的 Java 代码字符串。
- 查找类或接口声明: 使用 cu.findAll(ClassOrInterfaceDeclaration.class) 查找所有类或接口声明。
-
遍历并提取类型信息:
- 使用 forEach 循环遍历找到的每个类或接口声明。
- 使用 cid.getNameAsString() 获取类名。
- 使用 cid.getExtendedTypes() 获取类继承的所有类型。
- 再次使用 forEach 循环遍历继承的每个类型,并使用 extType.getNameAsString() 获取类型名称。
运行结果:
Class Name: Foo Extended Type: String
关键点:
- 使用 ClassOrInterfaceDeclaration.getExtendedTypes() 方法获取继承的类型,可以避免直接解析类型字符串,从而避免 FQ 名称被分解的问题。
- 这种方法只提取了类或接口直接继承的类型,如果需要提取所有间接继承的类型,则需要使用递归方法。
注意事项
- 该方法仅适用于提取类或接口声明中 extends 或 implements 关键字后的类型引用。
- 如果需要提取方法参数、局部变量等其他位置的类型引用,需要使用不同的 JavaParser API。
- 在使用 JavaParser 时,需要注意其版本兼容性,不同版本的 API 可能有所不同。
总结
本文介绍了一种使用 JavaParser 解析 Java 代码时,提取类或接口声明中的类型引用的方法,并解决了 FQ 名称被错误分解的问题。通过使用 ClassOrInterfaceDeclaration.getExtendedTypes() 方法,我们可以准确地提取所需的类型名称,避免不必要的中间结果。希望本文能帮助您更好地使用 JavaParser 进行 Java 代码分析。










