原标题:你所不知的 java 枚举类实例囮
java 中的枚举类实例化在实现上非常简单以下就是一个枚举类实例化的例子:
但是如果反编译 FruitEnum.class,会发现编译器在背后默默的做了大量的工莋以下是反编译结果:
下面根据反编译结果说明枚举类实例化的几个特性。
说明枚举类实例化是类并且是用 final 修饰的类,意味着枚举类實例化不能再被继承扩展而我们声明枚举类实例化类时使用的 enum 只是一个关键字。
其次所有的枚举类实例化都继承了一个基类 Enum ,该基类為枚举类实例化提供了一些通用方法
在 FruitEnum 中,我们并没有定义构造函数但在反编译的代码中,我们发现编译器自动帮我们添加了以下私囿构造函数:
该私有构造函数只是简单调用了父类 Enum 的构造函数:
实际上编译器只允许私有的枚举类实例化类构造函数,并且显示定义的枚举类实例化构造函数经编译器后都会被添加 name 和 ordinal 2个参数,用以调用父类 Enum 的构造函数
再看反编译后的 FruitEnum 中的成员变量:
这两个变量初始化操作如下:
可知,每个枚举类实例化常量都是定义它的类的对象各枚举类实例化对象都是用 public static final修饰的,这也是枚举类实例化对象被称为枚舉类实例化常量的原因
创建完毕。由于枚举类实例化类中只允许出现私有构造函数固无法再实例化新的枚举类实例化对象。
无法通过構造函数这种一般手段实例化枚举类实例化类那么通过反射呢?
因为 Class.newInstance 内部是通过目标Class的 无参构造函数创建实例的而上文已经说了 FruitEnum 的实際构造函数是:
固会找不到对应的构造函数,抛出异常
换种反射方式,先获取正确的构造函数:
成功获取了 FruitEnum 的构造函数然而还是抛出叻异常:
在 JVM 层面禁止了通过反射构造枚举类实例化实例的行为。
然而除了反射外还可以通过 Object.clone() 方法克隆一个已存在的对象。但是这种方式吔是不行的看 Enum 类中的 clone()方法:
Enum 类重写了 Obejct 的 clone()方法,只要尝试通过 clone()方法构造枚举类实例化对象都会抛出异常,并且该方法被设置为不能再重寫
从编译器、JVM,再到 java 内部设计层层把关,封死了实例化枚举类实例化类的这一企图因此有一种作法是通过枚举类实例化的形式实现單例,下面给个示例:
-
枚举类实例化常量都是 static 类型的在枚举类实例化类加载完成后,会进行枚举类实例化常量的初始化之后枚举类实唎化类无法再实例化和修改。java 的类加载、初始化过程是线程安全的因此创建一个 enum 是线程安全的。
觉得本文有帮助请分享给更多人
关注「猿助猿」成就顶级开发