简体   繁体   English

Java 反思:如何获取评论?

[英]Java reflection: How to get comments?

I have faced some difficulties with Java parsing.我在解析 Java 时遇到了一些困难。 I need somehow to get comments of class, fields, methods etc. via reflection.我需要以某种方式通过反射获得 class、字段、方法等的评论。

I have found JavaParser and it looks like it can elicit comments but I haven't got how to do it as all the examples just parse given string.我找到了 JavaParser ,看起来它可以引发评论,但我不知道如何去做,因为所有示例都只是解析给定的字符串。 I have found TypeSolver that can take Canonical name but it looks like that it can't work with comments.我发现TypeSolver可以采用规范名称,但它看起来无法使用注释。

My question is how to find comments if I have only Class<?> and also the project has some other jar's that should also be introspected.我的问题是如果我只有Class<?>并且该项目还有其他一些也应该反省jar's ,如何找到评论。 Via debugging I see the original source code and it looks like that it is possible to do somehow.通过调试,我看到了原始源代码,看起来可以以某种方式进行。
Thanks.谢谢。

PS I have source code, I need to match Class<?> with source code and then extract comments via JavaParser PS我有源码,我需要用源码匹配Class<?>然后通过JavaParser提取注释

First of all, you cannot directly get comments using reflection, and you cannot get them by using a library that reads the ".class" file.首先,不能直接使用反射获取注释,也不能使用读取“.class”文件的库获取注释。 The information is not present the ".class" file, and reflection only knows about information is directly available from there.信息不存在于“.class”文件中,反射只知道可以直接从那里获得的信息。

As people have pointed out, you can only get comments if you have the source code.正如人们所指出的,只有拥有源代码才能获得评论。 And if you have a source code file you should be able to extract comments using JavaParser or (possibly) some other library, ... or by writing your own parser.如果您有源代码文件,您应该能够使用JavaParser或(可能)其他一些库提取注释,...或通过编写自己的解析器。

The problem will be mapping from a Class object to the corresponding source code file.问题将是从Class对象映射到相应的源代码文件。 Let us assume that you have multiple source trees corresponding to multiple JARs on the application's classpath.让我们假设您有多个源代码树对应于应用程序类路径上的多个 JAR。 You will need:你会需要:

  • the URIs for each JAR or directory on the classpath,类路径上每个 JAR 或目录的 URI,
  • a mapping from each URI to a corresponding source tree.从每个 URI 到相应源树的映射。

The approach would be:方法是:

  1. Get the fully qualified class name from the Class object.Class对象中获取完全限定的类名。
  2. Map the classname to a relative Java source path;将类名映射到相对的 Java 源路径; eg foo.bar.Baz would become foo/bar/Baz.java例如foo.bar.Baz会变成foo/bar/Baz.java
  3. Use clazz.getProtectionDomain().getCodeSource().getLocation().toURI() to get the URI from whence the class was loaded.使用clazz.getProtectionDomain().getCodeSource().getLocation().toURI()获取加载类的 URI。
  4. Map the URI to the corresponding source tree ... using your mappings.使用您的映射将 URI 映射到相应的源树。
  5. Resolve the relative path relative to the root of the source tree.解析相对于源树根的相对路径。
  6. Open the source file.打开源文件。

Some of the above steps could present problems.上述某些步骤可能会出现问题。 For example:例如:

  • in step 2, you need to deal with nested classes,在第 2 步中,您需要处理嵌套类,
  • in step 3, getCodeSource() could return null ,在第 3 步中, getCodeSource()可以返回null
  • in step 3, the resulting URI could have a weird protocol,在第 3 步中,生成的URI可能有一个奇怪的协议,
  • if your mapping are incomplete, step 4 could fail,如果您的映射不完整,第 4 步可能会失败,
  • if your source code doesn't match the code you are executing, step 5 could fail.如果您的源代码与您正在执行的代码不匹配,则步骤 5 可能会失败。

Once you have the source file open, you construct a Reader and parse the source code ... using your chosen Java parser.打开源文件后,您可以构建一个Reader并解析源代码……使用您选择的 Java 解析器。


If yours was a "green field" project, it may be simpler to define a custom annotation type (retention == runtime) and turn your comments into annotations.如果您的项目是“绿地”项目,那么定义自定义注释类型(retention == runtime)并将您的注释转换为注释可能会更简单。 These annotations can be extracted simply and quickly, with none of the possible failure modes in the above.这些注释可以简单快速地提取,没有上述可能的故障模式。


I haven't got how to do it as all the [JavaParser] examples just parse given string.我不知道怎么做,因为所有 [JavaParser] 示例都只是解析给定的字符串。

The javadoc shows that you can use a JavaParser instance to parse a File , an InputStream , a Reader or a String . javadoc显示您可以使用JavaParser实例来解析FileInputStreamReaderString

I doubt that comments are contained in compiled code - so there is no way to do it by reflection.我怀疑编译后的代码中是否包含注释——所以没有办法通过反射来做到这一点。 Closest tool to do it would be XDoclet-1/2 which parsed javadoc tags and used them to generate other stuff (and this inspired annotations) - but this tool is obsolete and not suppported anymore最接近的工具是 XDoclet-1/2,它解析 javadoc 标签并使用它们来生成其他东西(以及这个启发注释) - 但这个工具已经过时,不再受支持

You can't.你不能。

Bytecode does not contain any comments, either inline or in JavaDoc format, from the original source code, as they are removed during the compilation phase. Bytecode不包含来自原始源代码的任何内联或 JavaDoc 格式的注释,因为它们在编译阶段被删除。

If you need the comments to somehow be transferred into the Bytecode , consider using Java's Annotations instead.如果您需要以某种方式将注释传输到Bytecode ,请考虑使用 Java 的Annotations

If you have the source code, it is probably in form of a JAR file.如果您有源代码,它可能是 JAR 文件的形式。 It is quite easy to locate the source file in the JAR file as the class provides both the package as well as local name.在 JAR 文件中定位源文件非常容易,因为该类同时提供了包名和本地名。 You have to consider a case with nested classes, but its is actually quite easy to implement.您必须考虑嵌套类的情况,但它实际上很容易实现。

When you've located the source file, you can easily parse it with JavaParser and retrieve the comments:找到源文件后,您可以使用 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());
    }

you should create annotation class and get value for your requirements.您应该创建注释类并为您的需求获取价值。 for example :例如 :

@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();
    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM