获取类path中的所有类
如何在运行时获得CLASSPATH
中所有可用类的列表?
在Eclipse IDE中,可以通过按Ctrl + Shift + T来完成 。
在Java中有任何方法来完成它?
通过将一个空String
传递给ClassLoader#getResources()
可以获得所有的类path根。
Enumeration<URL> roots = classLoader.getResources("");
你可以像下面这样构build一个基于URL
的File
:
File root = new File(url.getPath());
您可以使用File#listFiles()
获取给定目录中所有文件的列表:
for (File file : root.listFiles()) { // ... }
您可以使用标准的java.io.File
方法来检查它是否是一个目录和/或获取文件名。
if (file.isDirectory()) { // Loop through its listFiles() recursively. } else { String name = file.getName(); // Check if it's a .class file or a .jar file and handle accordingly. }
根据唯一的function要求,我想reflection库更准确地是你想要的。
这是我写的做的。 我敢肯定,如果你在类path中做了任何奇怪的事情,它并没有得到任何东西,但它似乎对我很好。 请注意,它实际上并没有加载类,它只是返回它们的名字。 这是因为它不会将所有类加载到内存中,并且由于我公司代码库中的某些类在错误的时间加载时会导致初始化错误。
public interface Visitor<T> { /** * @return {@code true} if the algorithm should visit more results, * {@code false} if it should terminate now. */ public boolean visit(T t); } public class ClassFinder { public static void findClasses(Visitor<String> visitor) { String classpath = System.getProperty("java.class.path"); String[] paths = classpath.split(System.getProperty("path.separator")); String javaHome = System.getProperty("java.home"); File file = new File(javaHome + File.separator + "lib"); if (file.exists()) { findClasses(file, file, true, visitor); } for (String path : paths) { file = new File(path); if (file.exists()) { findClasses(file, file, false, visitor); } } } private static boolean findClasses(File root, File file, boolean includeJars, Visitor<String> visitor) { if (file.isDirectory()) { for (File child : file.listFiles()) { if (!findClasses(root, child, includeJars, visitor)) { return false; } } } else { if (file.getName().toLowerCase().endsWith(".jar") && includeJars) { JarFile jar = null; try { jar = new JarFile(file); } catch (Exception ex) { } if (jar != null) { Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); int extIndex = name.lastIndexOf(".class"); if (extIndex > 0) { if (!visitor.visit(name.substring(0, extIndex).replace("/", "."))) { return false; } } } } } else if (file.getName().toLowerCase().endsWith(".class")) { if (!visitor.visit(createClassName(root, file))) { return false; } } } return true; } private static String createClassName(File root, File file) { StringBuffer sb = new StringBuffer(); String fileName = file.getName(); sb.append(fileName.substring(0, fileName.lastIndexOf(".class"))); file = file.getParentFile(); while (file != null && !file.equals(root)) { sb.insert(0, '.').insert(0, file.getName()); file = file.getParentFile(); } return sb.toString(); } }
要使用它:
ClassFinder.findClasses(new Visitor<String>() { @Override public boolean visit(String clazz) { System.out.println(clazz) return true; // return false if you don't want to see any more classes } });
您可以使用来自Guava库的com.google.common.reflect
包中的实用程序类。 例如,要获得特定包装中的所有课程:
ClassLoader cl = getClass().getClassLoader(); Set<ClassPath.ClassInfo> classesInPackage = ClassPath.from(cl).getTopLevelClassesRecursive("com.mycompany.mypackage");
这是简洁的,但是与其他答案描述相同的注意事项仍然适用,即通常只会find由“标准”类加载器(例如URLClassLoader
)加载的类。
每隔一段时间我都在寻找这个。 这很困难,因为即使你设法findclasspath上的所有东西,也可能找不到给定的类加载器可用的所有东西(例如,我曾经从一个直接从DB加载类定义的项目上工作过)。
在这一点上最好的select可能是看看spring。 他们扫描类path上的类,看看是否有任何注解,他们需要kickstart的东西。
这里接受的答案是一个很好的开始:
在运行时扫描Java注释
我build议使用Spring的PathMatchingResourcePatternResolver ;
它将会从IDE或文件系统启动软件包。
欲了解更多详情请查看我的logging:
如何从一个包中获取资源