Как читать структуру файлов Java с помощью Java? - PullRequest
4 голосов
/ 14 апреля 2010

Я пытаюсь прочитать файл 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

Заранее спасибо:)

Ответы [ 5 ]

6 голосов
/ 14 апреля 2010

Этого можно достичь с помощью API компилятора Java (представлен в Java 6). К сожалению, это решение ограничено JDK от Sun. Следовательно, вам необходимо установить 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);
}

Когда я передаю этот метод a File, содержимое которого является вашим образцом, я получаю этот вывод:

class name: Test
method name:
addTest
deleteTest

К сожалению, я еще не выяснил, где хранится имя пакета.

3 голосов
/ 14 апреля 2010

Его цель - проанализировать код Java и сообщить о его содержимом.С помощью Reflection вы можете делать такие вещи, как:

 Class.forName(className).getDeclaredMethods();
  • Java также имеет Java Mirror API с похожей функциональностью, но используется не так часто.

Оба эти решения не требуют сторонних библиотек или инструментов.

0 голосов
/ 14 апреля 2010

Вам не нужно делать это, анализируя файл Java самостоятельно! Java уже содержит способ получения информации о своих собственных классах, методах и пакетах: она называется отражение .

Посмотрите на класс java.lang.Class . Каждый экземпляр этого класса представляет определенный класс Java и содержит методы для возврата имени класса, пакета, в котором он находится, методы, которые он содержит, и много дополнительной информации.

Также стоит обратить внимание на пакет java.lang.reflect , поскольку некоторые методы Class возвращают типы из этого пакета. Пакет содержит классы для представления таких вещей, как методы, типы, поля и т. Д.

Чтобы получить Class экземпляр вашего класса Test, вы можете использовать следующий код:

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

Возвращает класс неизвестного типа, что означает вопросительный знак в угловых скобках, если вы не знакомы с обобщениями. Почему тип экземпляра класса неизвестен, потому что вы указываете имя класса со строкой, которая анализируется во время выполнения. Во время компиляции Java не может быть уверена, что строка, переданная в forName, даже вообще представляет действительный класс.

Однако, testclass, как определено выше, подойдет для получения имени класса, методов и содержащего пакета.

0 голосов
/ 14 апреля 2010

Мы используем анализатор кода Java PMD для решения аналогичной проблемы. Это полезно.

http://pmd.sourceforge.net/

0 голосов
/ 14 апреля 2010

Единственным трудным является то, что код Java может быть неправильно отформатирован. например, объявление функции может быть разбито на несколько строк.

Окончательное решение - создать автоматы для токенизации исходного кода, а затем применить некоторую технику компилятора, чтобы получить то, что вы хотите от проанализированных данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...