枚举
- Why:为什么需要枚举
- What:枚举是什么;
- How:枚举怎么实现
- When:枚举什么时候使用
- Where:枚举在哪里使用
- Other:使用枚举会带来什么问题?
What:枚举是什么
How:枚举是怎么实现的
- 实验代码
enum Season {
SPRING,
SUMMER,
AUTUMN,
WINTER;
}
- 使用jad编译代码
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: Season.java
final class Season extends Enum
{
public static Season[] values()
{
return (Season[])$VALUES.clone();
}
public static Season valueOf(String name)
{
return (Season)Enum.valueOf(EnumTest/Season, name);
}
private Season(String s, int i)
{
super(s, i);
}
public static final Season SPRING;
public static final Season SUMMER;
public static final Season AUTUMN;
public static final Season WINTER;
private static final Season $VALUES[];
static
{
SPRING = new Season("SPRING", 0);
SUMMER = new Season("SUMMER", 1);
AUTUMN = new Season("AUTUMN", 2);
WINTER = new Season("WINTER", 3);
$VALUES = (new Season[] {
SPRING, SUMMER, AUTUMN, WINTER
});
}
}
- 从jad编译得到的代码,可以看出创建了一个继承了
Enum
的Season
类; - 每个枚举类型实质上是一个
Season
类对象的引用;
枚举的线程安全
- 当一个Java类第一次被真正使用到的时候静态资源被初始化、Java类的加载和初始化过程都是线程安全的。所以,创建一个enum类型是线程安全的。
Enum
类
When and Where:枚举在什么时候可以使用
- 单例
枚举和单例
-
枚举是实现单例的推荐方式,原因是枚举可以保证线程安全和序列化的安全。
-
实现方式
public enum Singleton { INSTANCE; }
-
使用方式
public static void main(String[] args) { Singleton s1 = Singleton.INSTANCE; Singleton s2 = Singleton.INSTANCE; System.out.println(s1 == s2); // 返回true }
-
枚举解决了线程安全问题
由枚举实现部分可以看出,枚举值实际是在静态块中初始化;当一个Java类第一次被真正使用到的时候静态资源被初始化、Java类的加载和初始化过程都是线程安全的(因为虚拟机在加载枚举的类的时候,会使用ClassLoader的loadClass方法,而这个方法使用同步代码块保证了线程安全)。所以,创建一个enum类型是线程安全的。
枚举解决了反序列化会破坏单例的问题(学完序列化之后再细看)