Java 获取类路径中的所有类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3222638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get all of the Classes in the Classpath
提问by arash
采纳答案by BalusC
You can get all classpath roots by passing an empty String
into ClassLoader#getResources()
.
您可以通过将空传递String
给ClassLoader#getResources()
.
Enumeration<URL> roots = classLoader.getResources("");
You can construct a File
based on URL
as follows:
File root = new File(url.getPath());
You can use File#listFiles()
to get a list of all files in the given directory:
您可以使用File#listFiles()
获取给定目录中所有文件的列表:
for (File file : root.listFiles()) {
// ...
}
You can use the standard java.io.File
methods to check if it's a directory and/or to grab the filename.
您可以使用标准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.
}
Depending on the sole functional requirement, I guess that the Reflections libraryis much more exactly what you want.
根据唯一的功能需求,我想Reflections 库更符合您的需求。
回答by Bill K
Every so-often I look for this. It's kind of difficult because even if you manage to find everything on the classpath, you might not find everything available to a given class loader (for instance, I worked on a project that loaded class definitions directly from a DB once).
我经常找这个。这有点困难,因为即使您设法在类路径上找到所有内容,您也可能无法找到给定类加载器可用的所有内容(例如,我曾参与过一个直接从 DB 加载类定义的项目)。
The best bet at this point is probably to look into Spring. They scan the classes on the classpath to see if any have annotations that they need to kickstart stuff.
此时最好的选择可能是研究 Spring。他们扫描类路径上的类以查看是否有任何需要启动的注释。
The accepted answer here is a good place to start:
这里接受的答案是一个很好的起点:
回答by Andy
Here's what I wrote to do it. I'm sure it doesn't get everything if you're doing anything weird with the classpath, but it seems to work well for me. Note that it doesn't actually load the classes, it just returns their names. This is so that it won't load all classes into memory, and because some classes in my company's codebase were causing initialization errors if loaded at the wrong time...
这是我写的内容。我敢肯定,如果您对类路径做了任何奇怪的事情,它不会得到一切,但它似乎对我来说效果很好。请注意,它实际上并不加载类,它只是返回它们的名称。这是为了它不会将所有类加载到内存中,并且因为如果在错误的时间加载,我公司代码库中的某些类会导致初始化错误......
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();
}
}
To use it:
要使用它:
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
}
});
回答by Matthew Wise
You can make use of utility classes from the com.google.common.reflect
package from the Guava library. E.g. to get all classes in a particular package:
您可以使用com.google.common.reflect
来自 Guava 库的包中的实用程序类。例如,获取特定包中的所有类:
ClassLoader cl = getClass().getClassLoader();
Set<ClassPath.ClassInfo> classesInPackage = ClassPath.from(cl).getTopLevelClassesRecursive("com.mycompany.mypackage");
This is concise however the same caveats as other answers describe, still apply, namely, that it will generally only find classes loaded by a 'standard' ClassLoader e.g. URLClassLoader
.
这很简洁,但是与其他答案描述的相同警告仍然适用,即它通常只会找到由“标准”类加载器加载的类,例如URLClassLoader
.