【问题标题】:ClassLoad an Enum typeClassLoad 枚举类型
【发布时间】:2015-01-21 06:16:56
【问题描述】:

如何通过 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();

导致抛出异常。

【问题讨论】:

  • 为了避免所有的反射,我会启动一个线程,它使用你新的 ClassLoader 并且其中的所有代码都应该是自然的。
  • @PeterLawrey 你是什么意思?自定义类加载器是它自​​己的 jar 中引导过程的一部分,它为类路径找到所有必要的库并执行一些其他逻辑,然后启动主服务器应用程序(在另一个 jar 中)。
  • 您可以访问枚举类代码吗?您可能必须显式编写公共构造函数。
  • 您是否尝试使用Enum.valueOf( containerClass, "name of an instance")
  • 请注意,我找到了一个更简单的解决方案并将其添加到我的答案中。

标签: java enums classloader


【解决方案1】:

为了扩展我的评论,我认为你会得到最干净的是这样的:

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&lt;?&gt; 到正确的枚举类型的未经检查的强制转换。但至少@SuppressWarnings 的范围是有限的。


编辑:

经过进一步检查,实际上有一种更简单的方法可以实现您所需要的,而无需知道实例的名称并且没有警告:

Class<?> containerClass = loader.loadClass("com.somepackage.app.Name");
containerClass.getEnumConstants()

【讨论】:

    【解决方案2】:

    加载枚举不会导致它初始化。您必须通过字段引用或方法引用来引用它。因此,即使是像 Name name = Name.SERVER;Name.SERVER.name(); 这样的简单语句也可以解决问题。

    请参阅 Java 虚拟机规范的 5. Loading, Linking, and Initializing 章中的 5.5 Initialization 部分。

    【讨论】:

      猜你喜欢
      • 2012-09-16
      • 2018-10-18
      • 2017-01-14
      • 2023-02-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多