更新:我的问题与Instantiate enum class无关。这个问题只需要使用现有值之一实例化枚举。我在问:为什么反射API会为实际存在的方法抛出NoSuchMethodException
??
以下代码是否正确运行,具体取决于Xpto
被声明为class
还是enum
。
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)
在两种情况下,编译的结果都是带有私有构造函数的类。在Xpto.class.getDeclaredConstructor();
中使用反射API不会报告有关Xpto
是枚举的事实的错误,但不是。它只是抛出一个枚举的情况,没有这样的方法Xpto.<init>()
。 这不是真的。因为该构造函数存在。
答案 0 :(得分:3)
这里来自Java documentation:
Enum中的最终克隆方法可确保枚举常量永远不会 被克隆,并通过序列化机制进行特殊处理 确保不会由于以下原因而创建重复的实例 反序列化。 禁止以反射方式实例化枚举类型。 总之,这四件事确保没有枚举类型的实例 存在超出枚举常量定义的范围。
答案 1 :(得分:2)
编辑:经过一些其他检查后,完全改变了我的答案...
好吧,您的constructor(..., private resultListService: ResultListService) {}
...
this.resultListService.resultList$
.subscribe(resultList => console.log('This is the updated resultList: ', resultList));
的输出很奇怪,您应该验证它是否正确。我的输出是这样的:
javap -private
因此,由编译器为您的final class Xpto extends java.lang.Enum{
public static final Xpto Bar;
private static final Xpto[] ENUM$VALUES;
static {};
private Xpto(java.lang.String, int); // see this line!
public static Xpto[] values();
public static Xpto valueOf(java.lang.String);
}
真正创建的构造函数是两个参数的构造函数,采用enum
和String
(枚举名称和值)。这是合乎逻辑的,因为在运行时所有酷枚举功能都需要名称和某种数字标识符。
因此,以这种方式更改代码会导致“更好”的错误消息:
int
结果:
Constructor<Xpto> constructor = Xpto.class.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
constructor.newInstance("Foo", 2);
答案 2 :(得分:-2)
因为您尝试从static方法访问非静态内部类,所以它是正常的