Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ClassLoad an Enum type

How would one go about instantiating an Enum type via a ClassLoader or similar mechanism? (I'm trying to keep everything under the same context classloader for a standalone server application).

I have something like:

ClassLoader loader = new CustomClassLoader(parent, libDir);

Thread.currentThread().setContextClassLoader(loader);

// trouble area
Class<?> containerClass = loader.loadClass("com.somepackage.app.Name$SERVER");

I had wrongly thought simply loading the Enum would be enough to kick it off (it's private constructor contains startup method calls and what-not).

Doing what I have above does not result in any exceptions, but the JVM just terminates after the last line and the server does not start up.

Obviously doing:

containerClass.newInstance();

Results in an exception being thrown.

like image 962
SnakeDoc Avatar asked Jan 20 '15 20:01

SnakeDoc


1 Answers

To expand on my comment, I think the cleanest you'll get is something like this:

public static <T extends Enum<T>> T loadEnum(ClassLoader loader, String classBinaryName, String instanceName) throws ClassNotFoundException {
    @SuppressWarnings("unchecked")
    Class<T> eClass = (Class<T>)loader.loadClass(classBinaryName);
    return Enum.valueOf(eClass, instanceName);
}

There is really no way to avoid the unchecked cast from Class<?> to a proper enum type. But at least the @SuppressWarnings is limited in scope.


Edit:

Upon further checking, there is actually a simpler way of achieving what you need, without needing to know the name of an instance and without warnings:

Class<?> containerClass = loader.loadClass("com.somepackage.app.Name");
containerClass.getEnumConstants()
like image 106
RealSkeptic Avatar answered Sep 23 '22 17:09

RealSkeptic