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.
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()
Loading an enum doesn't cause it to initialize. You have to reference it through either a field reference or a method reference. So even a simple statement like Name name = Name.SERVER;
or Name.SERVER.name();
would do the trick.
See section 5.5 Initialization in chapter 5. Loading, Linking, and Initializing of the Java Virtual Machine Specification.