java - 为什么反射 API 会为现有的枚举构造函数抛出 NoSuchMethodException?
问题描述
更新:我的问题与Instantiate 枚举类无关。该问题只需要使用现有值之一实例化枚举。我在问:为什么反射 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)
在这两种情况下,编译的结果都是带有私有构造函数的类。使用反射 API不会报告关于作为枚举事实的错误,而不是。它只是抛出对于枚举的情况没有这样的方法。这不是真的。因为那个构造函数存在。Xpto.class.getDeclaredConstructor();
Xpto
Xpto.<init>()
解决方案
这是来自Java文档:
Enum 中的 final clone 方法确保了枚举常量永远不会被克隆,而序列化机制的特殊处理确保了不会因为反序列化而创建重复的实例。禁止枚举类型的反射实例化。这四件事一起确保枚举类型的实例不存在超出枚举常量定义的实例。
推荐阅读
- amazon-dynamodb - 从 JSON 或 CSV 将 50K 记录加载到 DynamoDB
- sql - POSTGRES - 使用 ON CONFLICT DO NOTHING 防止串行增量
- oracle - 提取源不包含指定的提取字段
- sql - 拆分日期范围和操作数据
- c# - 如何使用带有 onchange 方法的输入字段来更新对象的属性以写入数据?
- python - 为什么我不能从 list(itertools.count()) 中用键盘中断 Python?
- python - 如何在 Django 的选项标签中显示 Selected 选项值 Selected?
- python - (Django Rest 框架)如何更新用户模型
- dart - 如何在 Dart 中为容器类指定数据类型
- c# - 使用 SMTP 客户端发送电子邮件