I have a problem, I wish to use reflection to generate instances of one of a set of classes at runtime. However, I have hit a snag. I want to get all of the classes involved to register themselves so the appropriate class can be chosen from a GUI. I can do this using a static code block in each file which provides a tidy OO solution. However, the java class loader specifically loads classes when they are required, hence if a needed class has not yet been used, it is not registered.
Short of directly providing a static list of names, or running through the underlying class/java files (which would break when packaged into a jar anyway), is there any way to force classes of certain packages to be loaded?
Basically, I want the ability to add new classes, from a specified superclass, without having to change/add any other code.
To clarify, your problem isn't about "dynamic class loading in Java", it's about dynamic class enumeration -- you know how to load classes, you just don't know what classes you want.
A quick Google came up with this page: http://forums.sun.com/thread.jspa?threadID=341935&start=0&tstart=0
Taken from that page, here's some sample code that ought to work:
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;
}
Spring Framework does component scanning based on annotations.
Take a look at ClassPathScanningCandidateComponentProvider class, for example. You can do the same thing based on interface / base class and it should work for all LOCAL classes. There is no way to do this for ALL classes in java.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With