我有一个问题,我希望使用反射在运行时生成一组类中的一个的实例。但是,我遇到了麻烦。我想让所有涉及的类都注册自己,这样就可以从GUI中选择合适的类。我可以在每个文件中使用静态代码块来提供整洁的OO解决方案。但是,java类加载器在需要时专门加载类,因此如果尚未使用所需的类,则不会注册它。
没有直接提供静态名称列表,或者运行底层的类/ java文件(无论如何打包到jar中时会破坏),有没有办法强制加载某些包的类?
基本上,我希望能够从指定的超类中添加新类,而无需更改/添加任何其他代码。
答案 0 :(得分:3)
澄清一下,你的问题不是关于“Java中的动态类加载”,而是关于动态类枚举 - 你知道如何加载类,你只是不知道你是什么类想。
Google快速推出了此页面:http://forums.sun.com/thread.jspa?threadID=341935&start=0&tstart=0
从该页面开始,这里有一些应该有效的示例代码:
public static Class[] getClasses(String pckgname)
throws ClassNotFoundException {
ArrayList<Class> classes = new ArrayList<Class>();
// Get a File object for the package
File directory = null;
try {
ClassLoader cld = Thread.currentThread().getContextClassLoader();
if (cld == null) {
throw new ClassNotFoundException("Can't get class loader.");
}
String path = '/' + pckgname.replace('.', '/');
URL resource = cld.getResource(path);
if (resource == null) {
throw new ClassNotFoundException("No resource for " + path);
}
directory = new File(resource.getFile());
} catch (NullPointerException x) {
throw new ClassNotFoundException(pckgname + " (" + directory
+ ") does not appear to be a valid package");
}
if (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
classes.add(Class.forName(pckgname + '.'
+ files[i].substring(0, files[i].length() - 6)));
}
}
} else {
throw new ClassNotFoundException(pckgname
+ " does not appear to be a valid package");
}
Class[] classesA = new Class[classes.size()];
classes.toArray(classesA);
return classesA;
}
答案 1 :(得分:2)
Spring Framework根据注释进行组件扫描。
例如,查看ClassPathScanningCandidateComponentProvider课程。你可以根据接口/基类做同样的事情,它应该适用于所有 LOCAL 类。对于java中的 ALL 类,无法执行此操作。
答案 2 :(得分:1)
Class.forName(“class name here”);
你将拥有一个带有类名的String变量。 假设您有一个字符串列表,其中包含您要加载的所有类名(并使用静态代码块自动注册:
for(String className:classesToBeLoaded) 的Class.forName(类名);
答案 3 :(得分:1)
通过这个例子:
public class MainClass {
public static void main(String[] args){
ClassLoader classLoader = MainClass.class.getClassLoader();
try {
Class aClass = classLoader.loadClass("com.jenkov.MyClass");
System.out.println("aClass.getName() = " + aClass.getName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
答案 4 :(得分:1)
如果你的课程在文件系统中的jar中有可能(这可能听起来很荒谬,但我看过从ldaps加载的类)
因此,如果您的类位于jar中的文件系统中,您可以执行以下操作:
下面的伪java:
String classPath = System.getClassPath();
String [] classPathParts = classpath.split(";"); // or :
String [] allTheClasses = []
for each ( file in classPathParts ) {
if( file is directory ) {
allTheClasses.addAll( file.contents );
} else if ( file is ".jar" ) {
allTheClasses.addAll( getZippedNamesFrom( file ) );
}
}
// At this point you would have all the classes in the array ( list ) .
String [] packageNames = {"a.b.c", "d.e.f" };
for each ( String clazzName in allTheClasses ) {
if ( packageNames.contains( clazzName.getPackageName() ) ) {
Class.forName( clazzName ); // load it and have the static block run
// Or run it your self
}
}
// End of the story.
很久以前我就是这样做的。
我使用这种方法在不到一秒的时间内加载大约70k +类名。在我的情况下,我动态地寻找大约10个类,所以整个过程花了我大约1.1秒。
答案 5 :(得分:1)
您可以使用ClassFinder
,
http://jmeter.apache.org/api/org/apache/jorphan/reflect/ClassFinder.html
答案 6 :(得分:0)
我建议将所有“动态”类放入一个包中。扫描该目录以获取每个文件名,然后在Class.forName()中使用它来加载和注册每个类。
我昨天刚问了一个类似的问题,得到了一些很好的反馈。