Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Class Loading in Java (Enumeration)

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.

like image 263
Hubris Avatar asked Jan 24 '23 07:01

Hubris


2 Answers

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;
}
like image 187
Daniel Pryden Avatar answered Feb 01 '23 16:02

Daniel Pryden


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.

like image 22
ChssPly76 Avatar answered Feb 01 '23 15:02

ChssPly76