在运行时查找包中的所有类(并调用静态方法) [英] Find all classes in package (& call static methods) at runtime
问题描述
我有一个包含很多类的程序包,这些类都有一个名为onLoad
的静态方法.我想在程序启动时调用onLoad
方法,但是我不想硬连接每一根,即classA.onLoad(); classB.onLoad();
等
I have a package in which there are many classes, and these classes all have a static method called onLoad
. I want to call the onLoad
method when the program starts, however I do not want to hard-wire each and every one, i.e. classA.onLoad(); classB.onLoad();
etc.
如何列出软件包com.foo.bar.asd
中的所有类,并对它们全部运行onLoad()
?
How can I list all classes in package com.foo.bar.asd
and run onLoad()
on all of them?
预先感谢
推荐答案
我发现这个问题很有趣,因此提出了一个解决方案.这里最棘手的部分是实际上找到给定程序包中的所有类.
I found this question quite interesting so I came up with a solution. The tricky part here is to actually find all classes that are in a given package.
在此示例中,我假设所有类都位于与类C
相同的包中,并且除C
之外的所有其他类均具有可能无法访问的onLoad
方法(即private
).然后,您可以使用以下示例代码.
In this example I assume that all classes are in the same package where the class C
is and that all classes except C
have an onLoad
method which may be inaccessible (i.e. private
). Then you can use the following example code.
public final class C {
public static void main(String[] args) throws Exception {
for (Class<?> cls : getClasses(C.class)) {
if (cls != C.class) {
Method onLoad = cls.getDeclaredMethod("onLoad");
onLoad.setAccessible(true);
onLoad.invoke(null);
}
}
}
private static List<Class<?>> getClasses(Class<?> caller)
throws IOException, URISyntaxException {
return Files.walk(getPackagePath(caller))
.filter(Files::isRegularFile)
.filter(file -> file.toString().endsWith(".class"))
.map(path -> mapPathToClass(path, caller.getPackage().getName()))
.collect(Collectors.toList());
}
private static Class<?> mapPathToClass(Path clsPath, String packageName) {
String className = clsPath.toFile().getName();
className = className.substring(0, className.length() - 6);
return loadClass(packageName + "." + className);
}
private static Path getPackagePath(Class<?> caller)
throws IOException, URISyntaxException {
String packageName = createPackageName(caller);
Enumeration<URL> resources = caller.getClassLoader()
.getResources(packageName);
return Paths.get(resources.nextElement().toURI());
}
private static String createPackageName(Class<?> caller) {
return caller.getPackage().getName().replace(".", "/");
}
private static Class<?> loadClass(String name) {
try {
return Class.forName(name);
} catch (ClassNotFoundException e) {
return null;
}
}
}
我已经省略了所有异常检查,像resources.nextElement()
这样的语句甚至可能引发异常.因此,如果您想解决这些情况,则需要在此处和此处添加一些检查.
I've omitted all exception checking and statements like resources.nextElement()
may even throw an exception. So if you want to cover those cases, you need to add a few checks here and there.
这篇关于在运行时查找包中的所有类(并调用静态方法)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!