面试系列:关于枚举的几个问题
   来源:我的内容我做主     2019年05月08日 09:43

Java 枚举是如何保证线程安全的?

因为 Java 类加载与初始化是 JVM 保证线程安全,而 Java enum 枚举在编译器编译后的字节码实质是一个 final 类,每个枚举类型是这个 final 类中的一个静态常量属性,其属性初始化是在该 final 类的 static 块中进行,而 static 的常量属性和代码块都是在类加载时初始化完成的,所以自然就是 JVM 保证了并发安全。不使用 synchronized 和 lock 如何创建一个线程安全的单例?

https://zmdlbr.github.io/2017/07/12/%E7%BB%86%E8%B0%88%E5%8D%95%E4%BE%8B%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/#more

为什么有人说在一些场景下通过枚举实现的单例是最好的方式,原因是什么?

除过枚举实现的单例模式以外的其他实现方式都有一个比较大的问题是一旦实现了 Serializable 接口后就不再是单例了,因为每次调用 readObject() 方法返回的都是一个新创建出来的对象(当然可以通过使用 readResolve() 方法来避免,但是终归麻烦),而 Java 规范中保证了每一个枚举类型及其定义的枚举变量在 JVM 中都是唯一的,在枚举类型的序列化和反序列化上 Java 做了特殊处理,序列化时 Java 仅仅是将枚举对象的 name 属性输出到结果中,反序列化时则是通过 java.lang.Enum 的 valueOf 方法来根据名字查找枚举对象,同时禁用了 writeObject、readObject、readObjectNoData、writeReplace 和 readResolve 等方法。Java 迭代器和枚举器的区别是什么?

Enumeration

枚举器接口是 JDK 1.0 提供的,适用于传统类,而 Iterator

迭代器接口是 JDK 1.2 提供的,适用于 Collections。

Enumeration 只有两个方法接口,我们只能读取集合的数据而不能对数据进行修改,而 Iterator 有三个方法接口,除了能读取集合的数据外也能对数据进行删除操作。

Enumeration 不支持 fail-fast 机制,而 Iterator 支持 fail-fast 机制(一种错误检测机制,当多线程对集合进行结构上的改变的操作时就有可能会产生 fail-fast 机制,譬如 ConcurrentModificationException 异常)。

总归现在尽量使用 Iterator 迭代器而不是 Enumeration 枚举器吧。

接口 属性 初始化