首页 > 解决方案 > 为什么反射 API 会为现有的枚举构造函数抛出 NoSuchMethodException?

问题描述

更新:我的问题与Instantiate 枚举类无关。该问题只需要使用现有值之一实例化枚举。我在问:为什么反射 API 会抛出NoSuchMethodException一个真正存在的方法

以下代码运行没有错误,取决于是否Xpto声明为classenum

class Xpto {
  // Bar; // include this for enum declaration
  private Xpto() {      
  }
}

public class App {
  public static void main(String[] args) throws Exception{
    Constructor<Xpto> constructor = Xpto.class.getDeclaredConstructor();
    constructor.setAccessible(true);
    constructor.newInstance();
  }
}

在这两种情况下都javap显示了一个构造函数private Xpto()。如果Xpto是一个类,那么结果javap -private是:

class Xpto {
  private Xpto();
}

如果Xpto是一个枚举,那么结果javap -private是:

final class Xpto extends java.lang.Enum<Xpto> {
  ...
  private Xpto();
  static {};
}

然而对于后者,它会引发异常:

Exception in thread "main" java.lang.NoSuchMethodException: Xpto.<init>()
    at java.lang.Class.getConstructor0(Unknown Source)

在这两种情况下,编译的结果都是带有私有构造函数的。使用反射 API不会报告关于作为枚举事实的错误,而不是。它只是抛出对于枚举的情况没有这样的方法。这不是真的。因为那个构造函数存在。Xpto.class.getDeclaredConstructor();XptoXpto.<init>()

标签: javaenums

解决方案


这是来自Java文档

Enum 中的 final clone 方法确保了枚举常量永远不会被克隆,而序列化机制的特殊处理确保了不会因为反序列化而创建重复的实例。禁止枚举类型的反射实例化。这四件事一起确保枚举类型的实例不存在超出枚举常量定义的实例。


推荐阅读