【面試題】Java單例設計模式-餓漢式枚舉(enum)單例

1、enum關鍵字

enum關鍵字是在Java1.5也就是Java SE5以後引入的一個新特性:它經過關鍵字enum來定義一個枚舉類,這個被定義的枚舉類繼承Enum類,這個枚舉類算是一種特殊類,它一樣能像其餘普通類同樣擁有構造器、方法,也可以實現接口,可是它不能再繼承其餘別的類,由於它的直接父類是Enum類,而且由於它默認的修飾符有final的存在,所以它沒法直接派生出其餘子類,除非將其使用abstract修飾。編程

按照《Java編程思想》中的原話來講:關鍵字enum能夠將一組具名的值的有限集合建立爲一種新的類型,而這些具名的值能夠做爲常規的程序組件來使用。多線程

在枚舉類出現以前Java是將常量放在接口或是放在普通類當中,而後使用public、static、final去修飾定義的常量,以下兩個例子:app

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;
}

在枚舉類型出現以後,就可使用枚舉類型來定義常量,這些枚舉類型成員_一、_二、_3都默認被public、static、final修飾,語法以下:spa

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

2、枚舉單例的實現

單例模式的特色有如下三個:code

  • 一、單例類只能有一個實例。
  • 二、單例類必須本身建立本身的惟一實例。
  • 三、單例類必須給全部其餘對象提供這一實例。

咱們能夠發現枚舉類型十分契合以上三個特色,而且咱們經過建立枚舉類型,能夠發現它其中每個類型成員其實都是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

利用這個特性,咱們就能夠經過以下代碼建立單例,同時又由於這個特性,決定了它只能屬於餓漢式單例模式blog

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!

3、枚舉單例的優缺點

優勢:接口

(1)可以避免多線程同步問題;

(2)可以防止反序列化從新建立對象;

(3)實現比起其它懶漢式、餓漢式單例來講十分簡潔,閱讀性好;

缺點:

(1)由於是餓漢式加載,因此會致使枚舉實例會長期存在於內存當中;

相關文章
相關標籤/搜索