天天看点

java 枚举 单例_Java枚举怎么保证单例

背景

面试问到枚举是怎么保证单例的,刚好看了篇文章,总结一下。

实现

声明一个枚举 Season:

public enum Season {

SPRING, SUMMER, AUTUMN, WINTER;

}

经过编译后:

public abstract class Season { // 生成和枚举同名的抽象类

Season SPRING = new Season$1();

Season SUMMER = new Season$2();

Season AUTUMN = new Season$3();

Season WINTER = new Season$4();

final class Season$1 extends Season { // 真正的实现类

Season$1("SPRING", 0); // 调用 Enum类 的构造方法

}

// 其它内部类同理

Season[] $VALUES = new Season[4]; // values() 会用上

$VALUES[0] = SPRING;

$VALUES[1] = SUMMER;

$VALUES[2] = AUTUMN;

$VALUES[3] = WINTER;

public static Season[] values(){

return (Season[]) $VALUES.clone(); // 利用了 $VALUES

}

public static Season valueOf(String s){

return (Season) Enum.valueOf(Season.class, s); // Enum.valueOf 的本质是反射

}

}

枚举 经过编译后生成 同名抽象类,抽象类的 内部类 才是真正实现类。

如何保证单例

Enum#clone 用 final 修饰并禁止克隆,Enum#readObject 禁止反序列化复制枚举,从而保证了枚举变量是单例的。

参考文献