java 枚举使用和原理-用javap分析class

1 示例代码

源码分析的示例代码如下
在这里插入图片描述

2 枚举原理

枚举类在编译后生成了一个抽象类 继承了ENUM,他的变量生成一个内部类继承了这个抽象类 然后实现了枚举的接口(如果该枚举类有interface),
内部类是抽象类的一个静态 final 的变量
内部类继承了抽象类提供的枚举类里的方法和ENUM的方法

2.1 Class文件

在这里插入图片描述
在编译后生成了的class文件如下,多了两个匿名内部类class文件。
在这里插入图片描述

2.1 枚举类的javap*****

在这里插入图片描述
上图可以看出这是继承了java.lang.Enum 且impl 定义的接口
但是这个是abstract 抽象类
所以一个枚举类不能继承其他类 但是可以实现多个接口
在这里插入图片描述
上图是其方法
在这里插入图片描述
上图是其构造方法 可以看出调用父类构造方法
多的两个 string int 是父类(Enum)的name ordinal

2.1 匿名内部类的javap*****

下图可以看出 编译后生成的子类 继承了抽象类 并且实现了接口的方法
在这里插入图片描述

2.1 java.lang.Enum<>

在这里插入图片描述
构造方法的name ordinal ,name就是枚举的变量名 如下图HANDLERONE
在这里插入图片描述
用名 来判断一个枚举里面是否包含
在这里插入图片描述
Enum禁用克隆
在这里插入图片描述

2.1 加载流程*****

在这里插入图片描述
看指令
0 New 匿名内部类
4 弹变量HANDLERONE到栈
7/9 弹变量(构造方法里的变量)到栈
11 调用自己的构造方法
14 赋值变量HANDLERON
17-31 重复HANDLERONE 来初始化HANDLERTWO
35 抽象类handlerrstrategies生成一个数组(VALUES变量)
40 获取HANDLERONE
43 存储
44 压栈
45-50 重复HANDLERONE 来把HANDLERTWO放到数组

Tips: 后面的数组因该就是抽象类handlerrstrategies的 VALUES变量
在这里插入图片描述

2.1 Main()测试

在这里插入图片描述

3 单例模式-枚举类

3.1 枚举类实现单例模式

在这里插入图片描述

3.2 原理分析

因为Java虚拟机会保证枚举对象的唯一性,因此每一个枚举类型和定义的枚举变量在JVM中都是唯一的。这是因为通过枚举原理可以看出,枚举类的变量的值就是静态内部类的初始化
Java虚拟机会保证枚举类型不能被反射并且构造函数只被执行一次。

为何要使用枚举类实现单例模式,是因为枚举类可以避免序列化和反射实例化多个的情况。
在序列化中,通过ObjectInputStream的readObject0()方法中可以看到调用了readEnum()方法,而readEnum是通过类名和类对象类找到一个唯一的枚举对象,找到后赋值返回。
而反射的newInstance是直接不实例化枚举类的对象,会直接报“Cannot reflectively create enum objects”,即不能用反射来创建枚举类型。
因此Effective JAVA书中推荐使用枚举类实现单例模式。

4 小结

1.枚举本质上是通过普通的类来实现的,只是编译器为我们进行了处理。
2.每个枚举类型都继承自java.lang.Enum,并自动添加了values和valueOf方法。
3.每个枚举常量是一个静态常量字段,使用内部类实现,该内部类继承了枚举类。
4.所有枚举常量都通过静态代码块来进行初始化,即在类加载期间就初始化。
5.通过把clone、readObject、writeObject这三个方法定义为final的,同时实现是抛出相应的异常。这样保证了每个枚举类型及枚举常量都是不可变的。可以利用枚举的这两个特性来实现线程安全的单例。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值