繁体   English   中英

如何使用Java读取Java文件结构?

[英]How to Read Java File Structure using Java?

我正在尝试读取一个java文件,并在控制台中显示包,类和方法名称。 这样的事情:

文件:Test.java

package tspec.test;

public class Test {
   public void addTest () {}
   public void deleteTest () {}
}

输出:

package name: tspec.test
class name: Test
method name:
addTest
deleteTest

提前致谢 :)

这可以使用Java Compiler API (在Java 6中引入)来完成。 不幸的是,这个解决方案仅限于Sun的JDK。 因此,您必须安装JDK, 并且必须在类路径中包含其tools.jar文件。

public void displayInformation(File javaSourceFile) throws Exception {
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

    // The file manager locates your Java source file for the compiler. Null arguments indicate I am comfortable with its default behavior.
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);

    // These will be parsed by the compiler
    Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(javaSourceFile);

    // Creates a new compilation task. This doesn't actually start the compilation process.
    // Null arguments indicate I am comfortable with its default behavior.
    CompilationTask task = compiler.getTask(null, null, null, null, null, fileObjects);

    // Cast to the Sun-specific CompilationTask.
    com.sun.tools.javac.api.JavacTaskImpl javacTask = (com.sun.tools.javac.api.JavacTaskImpl) task;

    // The Sun-specific JavacTaskImpl can parse the source file without compiling it, returning 
    // one CompilationUnitTree for each JavaFileObject given to the compiler.getTask call (only one in our case).
    Iterable<? extends CompilationUnitTree> trees = javacTask.parse();
    CompilationUnitTree tree = trees.iterator().next();

    // Create a class that implements the com.sun.source.tree.TreeVisitor interface.
    // The com.sun.source.util.TreeScanner is a good choice because it already implements most of the logic.
    // We just override the methods we're interested in.
    class MyTreeVisitor extends TreeScanner<Void, Void> {

        @Override
        public Void visitClass(ClassTree classTree, Void p) {
            System.out.println("class name: " + classTree.getSimpleName());
            System.out.println("method name:");
            return super.visitClass(classTree, p);
        }

        @Override
        public Void visitMethod(MethodTree methodTree, Void p) {
            System.out.println(methodTree.getName());
            return super.visitMethod(methodTree, p);
        }

    }

    tree.accept(new MyTreeVisitor(), null);
}

当我传递这个方法的File其内容是你的样本,我收到这个输出:

class name: Test
method name:
addTest
deleteTest

不幸的是,我还没有弄清楚包名存储的位置。

它的目的是内省Java代码并报告它的内容。 使用Reflection,您可以执行以下操作:

 Class.forName(className).getDeclaredMethods();

这两种解决方案都不需要第三方库或工具。

唯一的困难是java代码可能格式不正确。 像函数声明一样可以在多行上传播。

最终的解决方案是创建一个自动机来首先标记源代码,然后应用一些编译器技术从解析的数据中获取您想要的内容。

我们使用PMD Java代码分析器来解决类似的问题。 它是有益的。

http://pmd.sourceforge.net/

您不必通过自己解析Java文件来完成此操作! Java已经包含了获取有关其自己的类,方法和包的信息的方法:它被称为反射

看看java.lang.Class类。 此类的每个实例都代表一个特定的Java类,并包含返回类名,它所在的包,它包含的方法以及更多信息的方法。

另外值得一看的是java.lang.reflect包,因为Class一些方法从这个包返回类型。 该包包含用于表示方法,类型,字段等内容的类。

要获取Test类的Class实例,可以使用以下代码:

Class<?> testclass = Class.forName("tspec.test.Test");

这将返回一个未知类型的类,如果您不熟悉泛型,则尖括号内的问号意味着什么。 为什么类实例的类型未知是因为您使用字符串指定类名,该字符串在运行时进行解析。 在编译时,Java无法确定传递给forName的字符串是否完全代表了有效的类。

但是,上面定义的testclass可以用于获取类的名称,方法和包含。

暂无
暂无

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

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