线程安全太监类 -- 枚举

一:枚举常识

使用枚举意义在于语义化表达,固定对象输出可以使用静态常量完成但不具备枚举优秀的语义化表达。且枚举相对多属性描述更加灵活

  1. 默认继承抽象类Enum,所以只能实现其它接口
  2. 构造函数不能被声明为public访问权限
  3. 所有对象自动添加public static final修饰符
  4. 非抽象枚举类默认采用final修饰,不可继承
  5. JDK1.5之后版本可以作为switch-case类型
  6. 接上一条可作为switch-case判断类型的有byte、short、int及其包装类以及String、enum
二:枚举示例

在这里插入图片描述
枚举一年四季时间跨度、季节特点描述。省略属性get/set方法部分

三:枚举类序列化

枚举对象在进行序列化的时候仅仅是将name属性输出到文件结果中,反序列化时会根据name属性调用valueOf()方法找到对应对象进行反序列化。所以需要注意一下两个地方枚举的运用:

  • 分布式环境下,请别删除枚举对象。否则程序运行过程中可能出现找不到枚举对象
  • 分布式接口返回枚举对象,如果服务端新增枚举值,那么老客户端可能会出现调用失败的情况

接下来看一下枚举类反序列化调用的方法valueOf()的实现,该方法是通过枚举对象name名字返回枚举对象
在这里插入图片描述
在这里插入图片描述

四:枚举类反射

在这里插入图片描述
反射获取对象都需要通过Class对象获取Constructor构造器,调用Constructor类的newInstance()方法进行实例化。如上图所示,该方法在第二个判断中判定如果是Enum类型就会抛出异常枚举类不能反射实例化

五:枚举类API

枚举类在JVM进行编译的时候除了继承自父类Enum的静态方法valueOf()、实例方法name()之外还会添加一个values()方法。编译后的枚举对象通过数组进行保存

5.1 valueOf

在这里插入图片描述
通过name属性查找获取并返回枚举对象

5.2 values

该方法在API文档中并不存在,编译器编译期间为enum类加上的静态方法,将枚举类所有对象转换为数组元素

5.3 name

在这里插入图片描述
枚举对象的名字通过在Enum类中的name属性维护,name()方法就是返回该属性值

六:EnumMap与EnumSet

在这里插入图片描述
JDK1.5新增的枚举类专属集合。EnumMap的key要求为枚举对象,value无限制。EnumSet则是与普通Set一致,枚举对象不能重复。EnumSet是一个抽象类,不能直接进行实例化,可以使用其方法noneOf()、allOf()获取实例化对象

七:枚举单例

一篇描述单例模式的文章中我就提过实现单例模式的懒汉法、饿汉法、双重锁校验、静态内部类。都是围绕着内存单一实例、线程安全、序列化安全这几个问题一展身手,枚举单例也是不错的一个选择,实现简单粗暴,没有线程安全与序列化安全问题。

7.1 线程安全

在这里插入图片描述
单例模式的线程安全都是发生在对象实例化期间,但是如果把一个定义好的枚举类反编译后会发现每个对象都被public static final 修饰,然后通过static静态代码块进行加载赋值。也就是说会随着类加载而初始化,也就是调用了ClassLoader的loadClass()方法,该方法线程安全。所以枚举实现单例天然线程安全

7.2 序列化安全

在这里插入图片描述
前面说到了枚举的序列化,仅仅是将name属性序列化到文件中。反序列化调用valueOf()方法通过name属性获取枚举对象。也就是说对象没有重新new实例创建,也就不存在序列化安全的问题。并且枚举类禁止了readObject、writeObject等序列化方式进行定制

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值