-2

我在 Java 解析方面遇到了一些困难。我需要以某种方式通过反射获得类、字段、方法等的评论。

我找到了 JavaParser,它看起来可以引发评论,但我不知道如何去做,因为所有示例都只是解析给定的字符串。我发现TypeSolver它可以采用规范名称,但看起来它不能与评论一起使用。

Class<?>我的问题是如果我只有并且该项目还有其他一些jar's也应该自省的评论,如何找到评论。通过调试,我看到了原始源代码,看起来可以以某种方式完成。
谢谢。

PS我有源代码,我需要Class<?>与源代码匹配,然后通过JavaParser提取注释

4

5 回答 5

3

首先,使用反射无法直接获取注释,也无法通过读取“.class”文件的库获取。信息不存在于“.class”文件中,反射只知道信息可以直接从那里获得。

正如人们所指出的,只有拥有源代码才能获得评论。如果你有一个源代码文件,你应该能够使用JavaParser或(可能)其他一些库来提取注释,......或者通过编写你自己的解析器。

问题将是从Class对象映射到相应的源代码文件。让我们假设您有多个源树对应于应用程序的类路径上的多个 JAR。你会需要:

  • 类路径上每个 JAR 或目录的 URI,
  • 从每个 URI 到相应源树的映射。

方法是:

  1. Class从对象中获取完全限定的类名。
  2. 将类名映射到相对 Java 源路径;例如foo.bar.Baz会变成foo/bar/Baz.java
  3. 用于clazz.getProtectionDomain().getCodeSource().getLocation().toURI()获取加载类的 URI。
  4. 将 URI 映射到相应的源代码树……使用您的映射。
  5. 解析相对于源树根的相对路径。
  6. 打开源文件。

上述某些步骤可能会出现问题。例如:

  • 在第 2 步中,您需要处理嵌套类,
  • 在第 3 步中,getCodeSource()可以返回null,
  • 在第 3 步中,结果URI可能有一个奇怪的协议,
  • 如果您的映射不完整,第 4 步可能会失败,
  • 如果您的源代码与您正在执行的代码不匹配,则第 5 步可能会失败。

打开源文件后,您就可以Reader使用您选择的 Java 解析器构建并解析源代码。


如果您的项目是“绿地”项目,那么定义自定义注释类型(保留 == 运行时)并将您的注释转换为注释可能会更简单。这些注释可以简单快速地提取出来,没有上述可能的故障模式。


我不知道该怎么做,因为所有 [JavaParser] 示例都只是解析给定的字符串。

javadoc显示您可以使用JavaParser实例来解析 a File、 an InputStream、 aReader或 a String

于 2020-04-08T07:43:48.593 回答
1

我怀疑注释是否包含在编译代码中-因此无法通过反射来做到这一点。最接近的工具是 XDoclet-1/2,它解析 javadoc 标签并使用它们来生成其他东西(以及这个受启发的注释) - 但是这个工具已经过时并且不再受支持

于 2018-03-13T14:58:18.733 回答
1

如果您有源代码,它可能是 JAR 文件的形式。在 JAR 文件中找到源文件非常容易,因为该类提供了包和本地名称。您必须考虑嵌套类的情况,但实际上它很容易实现。

找到源文件后,您可以使用 JavaParser 轻松解析它并检索注释:

    String classText = "public class Dummy{\n" + "//Comment\n" + "}";
    StringReader reader = new StringReader(classText);
    CompilationUnit compilationUnit = JavaParser.parse(reader, true);

    for (Comment comment : compilationUnit.getAllContainedComments()) {
        System.out.println(comment.getContent());
    }
于 2018-04-23T18:22:36.760 回答
0

你不能。

Bytecode不包含原始源代码中的任何内联或 JavaDoc 格式的注释,因为它们在编译阶段被删除。

如果您需要以某种方式将注释转移到 . Bytecode,请考虑改用 Java 的注释

于 2018-03-13T15:08:11.007 回答
-1

您应该创建注释类并根据您的要求获得价值。例如 :

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface Report {
    String value();
}



public class ReportClass{
    @Report("this is comment")
    private String atmLastTrxAmount;
}



for (Field declaredField : ReportClass.class.getDeclaredFields()) {
    declaredField.setAccessible(true);
    String relatedFieldComment = declaredField.getAnnotation(Report.class).value();
    ...
}
于 2020-04-08T06:47:32.550 回答