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 禁止反序列化复制枚举,从而保证了枚举变量是单例的。

参考文献

猜你喜欢

转载自www.cnblogs.com/mougg/p/12966368.html
今日推荐