在 Java 中获取包内的类文件数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10910510/
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 a array of class files inside a package in Java
提问by AurA
I need a Class[] of all the class files contained in one of my source packages in Java.
我需要一个包含在我的 Java 源包之一中的所有类文件的 Class[]。
I could n't find a standard method to do it in one shot. If someone can write a function to fetch that list would be really helpful.
我找不到一种标准的方法来一次性完成。如果有人可以编写一个函数来获取该列表,那将非常有帮助。
Class[] myClasses = yourfunction(); // Return a list of class inside a source package in the currently working project in java
采纳答案by AurA
I am able to solve this problem using normal file I/O and search mechanism. You can check the answer as posted here.
我可以使用普通的文件 I/O 和搜索机制来解决这个问题。您可以查看此处发布的答案。
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;
}
回答by Cfx
Did not try this on all VMs, but on a recent Oracle VM there is a shorter way:
没有在所有 VM 上都尝试过,但在最近的 Oracle VM 上有一个更短的方法:
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());
}
This will print out the names of the resources in the package, so you can use getResource(...)
on them. The call url.getContent()
will return an instance of sun.net.www.content.text.PlainTextInputStream
which is a VM specific class.
这将打印出包中资源的名称,以便您可以使用getResource(...)
它们。该调用url.getContent()
将返回一个实例,sun.net.www.content.text.PlainTextInputStream
该实例是 VM 特定的类。