ClassLoad 一个 Enum 类型
ClassLoad an Enum type
如何通过 ClassLoader 或类似机制实例化 Enum 类型? (我试图将所有内容都保存在独立服务器应用程序的同一上下文类加载器下)。
我有类似的东西:
ClassLoader loader = new CustomClassLoader(parent, libDir);
Thread.currentThread().setContextClassLoader(loader);
// trouble area
Class<?> containerClass = loader.loadClass("com.somepackage.app.Name$SERVER");
我错误地认为只需加载 Enum 就足以启动它(它的私有构造函数包含启动方法调用等等)。
执行我上面的操作不会导致任何异常,但是 JVM 在最后一行之后终止并且服务器没有启动。
显然在做:
containerClass.newInstance();
导致抛出异常。
加载枚举不会导致其初始化。您必须通过字段引用或方法引用来引用它。因此,即使像 Name name = Name.SERVER;
或 Name.SERVER.name();
这样的简单语句也可以解决问题。
请参阅 Java 虚拟机规范的 5.5 Initialization in chapter 5. Loading, Linking, and Initializing 部分。
为了扩展我的评论,我认为你会得到的最干净的东西是这样的:
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);
}
确实没有办法避免从 Class<?>
到正确枚举类型的未经检查的转换。但至少 @SuppressWarnings
的范围有限。
编辑:
经过进一步检查,实际上有一种更简单的方法可以实现您的需要,无需知道实例的名称并且没有警告:
Class<?> containerClass = loader.loadClass("com.somepackage.app.Name");
containerClass.getEnumConstants()
如何通过 ClassLoader 或类似机制实例化 Enum 类型? (我试图将所有内容都保存在独立服务器应用程序的同一上下文类加载器下)。
我有类似的东西:
ClassLoader loader = new CustomClassLoader(parent, libDir);
Thread.currentThread().setContextClassLoader(loader);
// trouble area
Class<?> containerClass = loader.loadClass("com.somepackage.app.Name$SERVER");
我错误地认为只需加载 Enum 就足以启动它(它的私有构造函数包含启动方法调用等等)。
执行我上面的操作不会导致任何异常,但是 JVM 在最后一行之后终止并且服务器没有启动。
显然在做:
containerClass.newInstance();
导致抛出异常。
加载枚举不会导致其初始化。您必须通过字段引用或方法引用来引用它。因此,即使像 Name name = Name.SERVER;
或 Name.SERVER.name();
这样的简单语句也可以解决问题。
请参阅 Java 虚拟机规范的 5.5 Initialization in chapter 5. Loading, Linking, and Initializing 部分。
为了扩展我的评论,我认为你会得到的最干净的东西是这样的:
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);
}
确实没有办法避免从 Class<?>
到正确枚举类型的未经检查的转换。但至少 @SuppressWarnings
的范围有限。
编辑:
经过进一步检查,实际上有一种更简单的方法可以实现您的需要,无需知道实例的名称并且没有警告:
Class<?> containerClass = loader.loadClass("com.somepackage.app.Name");
containerClass.getEnumConstants()