我需要枚举包中的所有类并将它们添加到List中.单个类的非动态版本如下:
List allClasses = new ArrayList(); allClasses.add(String.class);
如何动态地添加包中的所有类及其所有子包?
更新:在阅读了早期答案之后,我试图解决另一个次要问题是绝对正确的,所以让我说明一下.我知道这是可能的,因为其他工具可以做到这一点.在这里查看新问题.
更新:再次阅读本文,我可以看到它是如何被误读的.我想在编译后从文件系统中枚举所有MY PROJECT'S类.
****更新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; }