Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用Java读取Java文件结构?_Java_File - Fatal编程技术网

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

如何使用Java读取Java文件结构?,java,file,Java,File,我试图读取一个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 提前感谢:)唯一的困难是jav

我试图读取一个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代码可能格式不好。像函数声明一样,可以在多行上展开

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

  • JavaAPI的
它的目的是内省Java代码并报告其内容。通过反射,您可以执行以下操作:

 Class.forName(className).getDeclaredMethods();
  • Java也有类似的功能,但并不常用

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

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


您不必自己解析Java文件!Java已经包含了一种获取自己的类、方法和包信息的方法:称为

看看这门课。这个类的每个实例代表一个特定的Java类,并包含返回类名的方法、它所在的包、它包含的方法以及更多信息

同样值得一看的是这个包,因为
Class
的一些方法从这个包返回类型。包包含表示方法、类型、字段等的类

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

Class<?> testclass = Class.forName("tspec.test.Test");
classtestclass=Class.forName(“tspec.test.test”);
这将返回一个未知类型的类,如果您不熟悉泛型,则尖括号内的问号就是这个意思。类实例的类型未知的原因是您使用字符串指定类名,该字符串在运行时解析。在编译时,Java甚至不能确定传递给
forName
的字符串是否表示有效的类


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

这可以使用(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);
}

不幸的是,我还没有弄清楚包名存储在哪里。

正则表达式可以处理多行,尽管我同意最终的解决方案是解析器。我认为海报可以访问.java文件而不是.class文件。当你说“读取java文件”时,你是指java源代码文件(.java)或者一个Java字节码文件(.class)?我想你可以看看
javac
的源代码,看看它是如何解析
.Java
文件的。您这样做仅仅是为了练习,还是某个更大的项目的一部分?使用“@Override public Void visitcomplationunit(CompilationUnitTree unit,Void arg){System.out.println(“Package:+unit.getPackageName()”;return super.visitcomplationunit(unit,arg);};”获取包。 class name: Test method name: addTest deleteTest