一、enum關鍵字 enum關鍵字是在Java1.5也就是Java SE5之後引入的一個新特性:它通過關鍵字enum來定義一個枚舉類,這個被定義的枚舉類繼承Enum類,這個枚舉類算是一種特殊類,它同樣能像其他普通類一樣擁有構造器、方法,也能夠實現介面,但是它不能再繼承其他別的類,因為它的直接父類是E ...
一、enum關鍵字
enum關鍵字是在Java1.5也就是Java SE5之後引入的一個新特性:它通過關鍵字enum來定義一個枚舉類,這個被定義的枚舉類繼承Enum類,這個枚舉類算是一種特殊類,它同樣能像其他普通類一樣擁有構造器、方法,也能夠實現介面,但是它不能再繼承其他別的類,因為它的直接父類是Enum類,並且因為它預設的修飾符有final的存在,因此它無法直接派生出其他子類,除非將其使用abstract修飾。
按照《Java編程思想》中的原話來說:關鍵字enum可以將一組具名的值的有限集合創建為一種新的類型,而這些具名的值可以作為常規的程式組件來使用。
在枚舉類出現之前Java是將常量放在介面或是放在普通類當中,然後使用public、static、final去修飾定義的常量,如下兩個例子:
public interface Constants2 { public static final int CONSTANT_1 = 1; public static final int CONSTANT_2 = 2; public static final int CONSTANT_3 = 3; } public class Constants { public static final int CONSTANT_1 = 1; public static final int CONSTANT_2 = 2; public static final int CONSTANT_3 = 3; }
在枚舉類型出現之後,就可以使用枚舉類型來定義常量,這些枚舉類型成員_1、_2、_3都預設被public、static、final修飾,語法如下:
public enum Constants { CONSTANT_1, CONSTANT_2, CONSTANT_3 }
但是Java枚舉類型輸出其常量的時候不像C /C++的枚舉那樣是數字,輸出的是其常量名,如果需要輸出其類型成員聲明時數字次序的話,需要調用ordinal()方法:
public enum Singleton2 { SHERLOCK, WASTON; } class Main{ public static void main(String[] args) { System.out.println(Singleton2.SHERLOCK); System.out.println(Singleton2.WASTON); System.out.println(Singleton2.SHERLOCK.ordinal()); System.out.println(Singleton2.WASTON.ordinal()); } } 輸出結果: SHERLOCK WASTON 0 1
二、枚舉單例的實現
單例模式的特點有以下三個:
- 1、單例類只能有一個實例。
- 2、單例類必須自己創建自己的唯一實例。
- 3、單例類必須給所有其他對象提供這一實例。
我們可以發現枚舉類型十分契合以上三個特點,並且我們通過創建枚舉類型,可以發現它其中每一個類型成員其實都是Singleton2這個枚舉類的一個實例。
public enum Singleton2 { SHERLOCK } class Main{ public static void main(String[] args) { Singleton2 sherlock = Singleton2.SHERLOCK; Singleton2 sherlock1 = Singleton2.SHERLOCK; System.out.println(sherlock == Singleton2.SHERLOCK); System.out.println(sherlock == sherlock1); System.out.println(Singleton2.SHERLOCK.getDeclaringClass()); } } 輸出結果: true true class com.sherlock.singleton.Singleton2
利用這個特性,我們就可以通過如下代碼創建單例,同時又因為這個特性,決定了它只能屬於餓漢式單例模式
public enum Singleton2 { SHERLOCK; public void print() { System.out.println("I am Sherlock!"); } } class Main{ public static void main(String[] args) { Singleton2 sherlock = Singleton2.SHERLOCK; System.out.println(Singleton2.SHERLOCK.getDeclaringClass()); sherlock.print(); } }
輸出結果如下:
class com.sherlock.singleton.Singleton2 I am Sherlock!
三、枚舉單例的優缺點
優點:
(1)能夠避免多線程同步問題;
(2)能夠防止反序列化重新創建對象;
(3)實現比起其它懶漢式、餓漢式單例來說十分簡潔,閱讀性好;
缺點:
(1)因為是餓漢式載入,所以會導致枚舉實例會長期存在於記憶體當中;