Вопрос по java – Получить массив файлов классов внутри пакета в Java [duplicate]

8

На этот вопрос уже есть ответ:

Можете ли вы найти все классы в пакете, используя отражение? 23 ответа

Мне нужен Class [] всех файлов классов, содержащихся в одном из моих исходных пакетов на Java.

Я не мог найти стандартный способ сделать это за один раз. Если кто-то может написать функцию для извлечения этого списка, было бы очень полезно.

Class[] myClasses = yourfunction();  // Return a list of class inside a source package in the currently working project in java
Смотрите здесь для обхода вручную (это не дурак) - / Stackoverflow.com вопросы / 176527 / ... Perception
Нет стандартного способа перечисления всех классов в данном пакете. В некоторых случаях это даже невозможно (подумайте о загрузке классов URLClassLoader из HTTP-URL: стандартного способа перечисления файлов в папке не существует). Joachim Sauer

Ваш Ответ

2   ответа
7

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

private static List<Class> getClassesForPackage(Package pkg) {
    String pkgname = pkg.getName();

    List<Class> classes = new ArrayList<Class>();

    // Get a File object for the package
    File directory = null;
    String fullPath;
    String relPath = pkgname.replace('.', '/');

    //System.out.println("ClassDiscovery: Package: " + pkgname + " becomes Path:" + relPath);

    URL resource = ClassLoader.getSystemClassLoader().getResource(relPath);

    //System.out.println("ClassDiscovery: Resource = " + resource);
    if (resource == null) {
        throw new RuntimeException("No resource for " + relPath);
    }
    fullPath = resource.getFile();
    //System.out.println("ClassDiscovery: FullPath = " + resource);

    try {
        directory = new File(resource.toURI());
    } catch (URISyntaxException e) {
        throw new RuntimeException(pkgname + " (" + resource + ") does not appear to be a valid URL / URI.  Strange, since we got it from the system...", e);
    } catch (IllegalArgumentException e) {
        directory = null;
    }
    //System.out.println("ClassDiscovery: Directory = " + directory);

    if (directory != null && directory.exists()) {

        // Get the list of the files contained in the package
        String[] files = directory.list();
        for (int i = 0; i < files.length; i++) {

            // we are only interested in .class files
            if (files[i].endsWith(".class")) {

                // removes the .class extension
                String className = pkgname + '.' + files[i].substring(0, files[i].length() - 6);

                //System.out.println("ClassDiscovery: className = " + className);

                try {
                    classes.add(Class.forName(className));
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException("ClassNotFoundException loading " + className);
                }
            }
        }
    } else {
        try {
            String jarPath = fullPath.replaceFirst("[.]jar[!].*", ".jar").replaceFirst("file:", "");
            JarFile jarFile = new JarFile(jarPath);
            Enumeration<JarEntry> entries = jarFile.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                String entryName = entry.getName();
                if (entryName.startsWith(relPath) && entryName.length() > (relPath.length() + "/".length())) {

                    //System.out.println("ClassDiscovery: JarEntry: " + entryName);
                    String className = entryName.replace('/', '.').replace('\\', '.').replace(".class", "");

                    //System.out.println("ClassDiscovery: className = " + className);
                    try {
                        classes.add(Class.forName(className));
                    } catch (ClassNotFoundException e) {
                        throw new RuntimeException("ClassNotFoundException loading " + className);
                    }
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(pkgname + " (" + directory + ") does not appear to be a valid package", e);
        }
    }
    return classes;
}
Слишком большой, должно быть проще ... Illidanek
@ Illidanek Да, вы можете определенно сократить некоторые строки кода из этого кода, а также может существовать лучшее решение, даже я хотел бы увидеть более короткий и более эффективный код, который выполняет ту же работу. AurA
Хороший ответ ... сэкономил много времени Sayak Choudhury
3

но на недавней виртуальной машине Oracle есть более короткий путь:

Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources("package/name/with/slashes/instead/dots");
    while (resources.hasMoreElements()) {
        URL url = resources.nextElement();
        System.out.println(url);
        System.out.println(new Scanner((InputStream) url.getContent()).useDelimiter("\\A").next());
    }

Это напечатает имена ресурсов в пакете, так что вы можете использоватьgetResource(...) на них. Вызовurl.getContent() вернет экземплярsun.net.www.content.text.PlainTextInputStream который является классом, специфичным для виртуальной машины.

Это не работает с jar под jdk 1.8.sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream бросает NPE при попытке прочитать с него. Vadzim

Похожие вопросы