当前位置:  开发笔记 > 编程语言 > 正文

如何枚举包中的所有类并将它们添加到List?

如何解决《如何枚举包中的所有类并将它们添加到List?》经验,为你挑选了1个好方法。

我需要枚举包中的所有类并将它们添加到List中.单个类的非动态版本如下:

List allClasses = new ArrayList();
allClasses.add(String.class);

如何动态地添加包中的所有类及其所有子包?


更新:在阅读了早期答案之后,我试图解决另一个次要问题是绝对正确的,所以让我说明一下.我知道这是可能的,因为其他工具可以做到这一点.在这里查看新问题.

更新:再次阅读本文,我可以看到它是如何被误读的.我想在编译后从文件系统中枚举所有MY PROJECT'S类.



1> Dave Dopson..:

****更新1(2012年)****

好的,我终于开始清理下面的代码片段了.我坚持使用它自己的github项目甚至添加了测试.

https://github.com/ddopson/java-class-enumerator

****更新2(2016)****

有关更强大且功能丰富的类路径扫描程序,请参阅https://github.com/lukehutch/fast-classpath-scanner/wiki.我建议先阅读我的代码片段以获得高级别的理解,然后使用lukehutch的工具进行制作.

****原帖(2010)****

严格来说,无法在包中列出类.这是因为包实际上只是一个命名空间(例如com.epicapplications.foo.bar),并且类路径中的任何jar文件都可能将类添加到包中.更糟糕的是,类加载器将按需加载类,而类路径的一部分可能位于网络连接的另一端.

可以解决更严格的问题.例如,JAR文件中的所有类,或JAR文件在特定包中定义的所有类.无论如何,这是更常见的情况.

不幸的是,没有任何框架代码可以轻松完成这项任务.您必须以类似于ClassLoader查找类定义的方式扫描文件系统.

网上有很多样本用于普通旧目录中的类文件.这些天我们大多数人都使用JAR文件.

要使用JAR文件,请尝试这个...

private static ArrayList> getClassesForPackage(Package pkg) {
    String pkgname = pkg.getName();
    ArrayList> classes = new ArrayList>();
    // 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 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;
}


谢谢你的代码,对我帮助很大.我发现了一个小问题:如果你的资源URL中有空格,它们会被urlencoded(即你的路径中最终得到'%20`).使用`directory = new File(fullPath)构造目录File时; `,这会导致`directory.exists()`返回`false`,因为它试图找到编码路径的文字匹配.这可以通过使用`directory = new File(resource.toURI());来代替(使用适当的异常处理)来解决.
@ddopson:它在新文件(resource.toURI())失败,因为构造函数遇到"jar:file:/opt/app/someDir/test.jar时会抛出"IllegalArgumentException:URI不是分层的"!/test/Test"由于我的类路径仅使用JAR文件构建它所遇到的URI类型.看看这个答案:http://stackoverflow.com/questions/7574965/in-java-how-can-i-construct-a-file-from-a-resource +我自己使用你的代码遇到过它.
推荐阅读
wurtjq
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有