天天看點

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 禁止反序列化複制枚舉,進而保證了枚舉變量是單例的。

參考文獻