【问题标题】:how get the fully qualified name of the java class如何获取java类的完全限定名
【发布时间】:2014-03-27 10:08:30
【问题描述】:

我有一个像下面这样的课程。

public class Login {
    private Keyword browser;
    private String page;
}

Keyword 是不同包中的一个类。我想在使用javaparser 解析Login 类时获取类Keyword 的完全限定名称。

【问题讨论】:

  • 正如@EJP 在他的回答中暗示的那样,除了解析源代码之外,您还必须至少进行最少数量的代码分析。例如。像这样:(1)查看类型引用是否已经是限定名称,(2)如果不存在,则查看是否存在导入,(3)否则将类型名称附加到包声明中。
  • 另请注意,JavaParser 已移至 GitHub github.com/javaparser/javaparser

标签: java javaparser


【解决方案1】:

使用 JavaParser 无法做到这一点,因为 JavaParser 不解析符号。要将名称关键字解析为类,您需要做几件事: * 实现适当的范围规则(您需要查找内部类,然后查找同一文件中的其他类,然后考虑导入...) * 它取决于用于编译的类路径:更改它相同的类可能会以不同方式解决

为此,应该编写一个符号解析器:它不是微不足道的而是可行的。如果您对该主题感兴趣,可以阅读我刚刚写的帖子How to build a symbol solver for Java, in Clojure。该帖子还包含一个代码链接,可在 GitHub 上免费获得。

来源:我是 JavaParser 贡献者

【讨论】:

    【解决方案2】:

    您可以使用 JavaParser 符号求解器:

    <dependency>
        <groupId>com.github.javaparser</groupId>
        <artifactId>javaparser-symbol-solver-core</artifactId>
        <version>3.14.5</version>
    </dependency>
    

    然后使用如下配置解析代码:

    CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(new ReflectionTypeSolver(), 
                                                         new JavaParserTypeSolver(sourceRoot));
    final ParserConfiguration config = new ParserConfiguration()
                    .setStoreTokens(true)
                    .setSymbolResolver(new JavaSymbolSolver(combinedTypeSolver));
    SourceRoot root = new SourceRoot(Paths.get("/path/to/project/"));
    root.parse("", config, (Path localPath, Path absolutePath, ParseResult<CompilationUnit> result) -> {
                    // Do something with the CompilationUnit
                    return Result.DONT_SAVE;
                });
    

    我们现在可以使用以下方法获取任何ReferenceType 的完全限定标识符:

    ResolvedType type = referenceType.resolve();
    String qualifiedName = type.getQualifiedName();
    

    【讨论】:

    • 太棒了——这也适用于我。但是,我仍然需要您其他答案中的 getClass(Node n1) 方法。没有等效的 API 吗?
    • @Fuhrmanator 我认为没有与该方法等效的 API。
    【解决方案3】:

    到目前为止似乎没有人阅读过这个问题,但如果您正在解析源代码,它要么在当前包中,要么是通过 import 语句导入的。

    我希望 Java 解析器编写者或用户知道这一点。

    【讨论】:

    • 如果有问题的类型来自通配符导入语句,则很难解析限定名称。
    【解决方案4】:

    我写了一个方法,可以根据ClassOrInterfaceDeclaration对象(JavaParser的最新版本)获取完全限定名称:

        private static String getFullyQualifiedName(ClassOrInterfaceDeclaration c2) {
            String name = "";
            ClassOrInterfaceDeclaration parentClass = c2.getParentNode().isPresent() ? getClass(c2.getParentNode().get()): null;
            if(parentClass!=null) {
                name+=getFullyQualifiedName(parentClass)+".";
            } else {
                CompilationUnit u = getCompilationUnit(c2);
                if(u!=null && u.getPackageDeclaration().isPresent()) {
                    name+=u.getPackageDeclaration().get().getNameAsString()+".";
                }
            }
            return name+c2.getNameAsString();
        }
    
        private static ClassOrInterfaceDeclaration getClass(Node n1) {
            while (!(n1 instanceof ClassOrInterfaceDeclaration)) {
                if(n1.getParentNode().isPresent()) {
                    n1 = n1.getParentNode().get();
                } else return null;
            }
            return (ClassOrInterfaceDeclaration)n1;
        }
    
        private static CompilationUnit getCompilationUnit(Node n1) {
            while (!(n1 instanceof CompilationUnit)) {
                if(n1.getParentNode().isPresent()) {
                    n1 = n1.getParentNode().get();
                } else return null;
            }
            return (CompilationUnit)n1;
        }
    

    如果你获得类的ClassOrInterfaceType,可以使用一个更简单的版本:

        private static String getFullyQualifiedName(ClassOrInterfaceType e) {
            String name = "";
            if(e.getScope().isPresent())
                name+=getFullyQualifiedName(e.getScope().get())+".";
            return name+e.getNameAsString();
        }
    

    我希望这对任何人都有帮助!

    【讨论】:

    【解决方案5】:

    如果您使用访问者,您似乎只能在源文件中获取开始和结束索引以获得类型名称。这不会让您获得完全限定的名称。

    因此,您也应该在自定义访问者中实现 visit(ImportDeclaration, A) 方法。然后,此方法必须存储导入声明,因此您可以稍后 - 当方法 visit(FieldDeclaration, A) 被调用时 - 引用导入的包并组装完全限定名称。

    【讨论】:

      【解决方案6】:

      JavaParser 不解析导入(无论如何,这通常不被认为是它的工作)。您必须手动单步执行导入语句并搜索 Keyword 是否属于它们。请记住,Java 隐式执行 import java.lang.*,否则您将无法解析 String 等类型。

      Spring Roo 有一个 JavaParserUtils 类,其中包含一个方法 getJavaType(CompilationUnitServices compilationUnitServices, ClassOrInterfaceDeclaration cid)。该类不是为 Roo 之外的使用而设计的,但您可以将其用作解决问题的模板。

      【讨论】:

        【解决方案7】:

        这可能是解决您问题的更好方法,

        使用实例。

        use of "Instance of" in java

        【讨论】:

          【解决方案8】:

          使用 Java 反射 (java.lang.reflect)

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-03-25
            • 2014-06-04
            • 1970-01-01
            • 2022-11-28
            • 2013-11-21
            • 2012-10-31
            • 2021-11-30
            • 2016-09-30
            相关资源
            最近更新 更多