Java 为什么反射API为现有枚举构造函数抛出NoSuchMethodException?
更新:我的问题与此无关。这个问题只需要用一个现有值实例化枚举。我在问:为什么反射API为一个真正存在的方法抛出Java 为什么反射API为现有枚举构造函数抛出NoSuchMethodException?,java,enums,Java,Enums,更新:我的问题与此无关。这个问题只需要用一个现有值实例化枚举。我在问:为什么反射API为一个真正存在的方法抛出NoSuchMethodException 根据Xpto是声明为class还是enum,以下代码运行时是否没有错误 class Xpto { // Bar; // include this for enum declaration private Xpto() { } } public class App { public static void main(
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();
}
}
如果Xpto
是一个枚举,那么javap-private的结果是:
class Xpto {
private Xpto();
}
final class Xpto extends java.lang.Enum<Xpto> {
...
private Xpto();
static {};
}
final类Xpto扩展java.lang.Enum{
...
私有Xpto();
静态{};
}
但对于后者,它抛出了一个例外:
Exception in thread "main" java.lang.NoSuchMethodException: Xpto.<init>()
at java.lang.Class.getConstructor0(Unknown Source)
线程“main”java.lang.NoSuchMethodException中的异常:Xpto.()
位于java.lang.Class.getConstructor0(未知源)
在这两种情况下,编译的结果都是一个带有私有构造函数的类。在Xpto.class.getDeclaredConstructor()中使用反射API
不报告有关Xpto
是枚举这一事实的错误,而不是。它只是抛出,对于枚举,没有这样的方法Xpto。
这不是真的。因为该构造函数存在。这里是来自Java的:
Enum中的最后一个克隆方法确保永远不能使用Enum常量
被克隆,并通过序列化机制进行特殊处理
确保不会由于以下原因而创建重复实例:
反序列化禁止枚举类型的反射实例化。
这四件事一起确保没有枚举类型的实例
超出枚举常量定义的范围
因为您试图从静态方法访问非静态的内部类,所以它的正常编辑:在一些额外的检查之后完全更改了我的答案 嗯,您的
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
(enum名称和值)。这是合乎逻辑的,因为在运行时,所有酷枚举特性都需要一个名称和某种数字标识符
因此,以这种方式更改代码会产生“更好”的错误消息:
Constructor<Xpto> constructor = Xpto.class.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
constructor.newInstance("Foo", 2);
那为什么要使用枚举?我不是该枚举的提供者。但我需要一个不同的内部值。可能重复“需要用新值实例化的枚举类型定义”。再次。。。那是不可能的。它描述了如何向
enum
添加一个新值。我没有看到来自javap的构造函数,只看到了参数less。这里是我的javap输出:。我正在使用JDK11。不过,我已经用JDK 8编译了它,并得到了相同的输出。@MiguelGamboa-hmm,这很奇怪。就我而言,这都是Oracle Java 8。也许JDK 11的javap实现中有一些变化,现在它计算回代码中的构造函数(删除两个自动参数)?但这也会很奇怪。。。可能是一个新问题的基础:-)你在哪里找到一个内部类?
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
at java.lang.reflect.Constructor.newInstance(Constructor.java:417)