天天看點

不一樣的Java Enum

Emum是在Java5中引入的新特性,從那開始,它被廣泛的用在不同的Java應用中,相比于C和C++的Enum,Java的Enum功能更加強大。但是很多開發人員暫時還沒意識到它的強大之處,在Enum的一些細節問題上把握的還不到位。Enum的特性及相關資料可以整理出一本書也不為過,這裡簡單對Enum做個大概。主要講解以下幾個方面。

不一樣的Java Enum
Java Enum

  1. Enum的介紹
  2. Enum的特性
  3. Enum的用法
  4. Enum的一些面試題
  5. Enum用法建議

什麼是Enum

Enum是一個Java的關鍵字,用于表示一個固定的常用值。例如,每周的天數,每年的月數等。Enum是一種類型,就像Class和Interface可以用于定義一系列的Enum常量

  • Enum常量隐式的加上了static和final,一旦被建立就無法修改
  • Enum提供了是類型安全的(type-safe)
  • Enum隐式的加上了values()方法,傳回一個數組包含所有的Enum常量
  • 兩個Enum常量可以使用

    ==

    equals()

    方法比較
  • Enum可以用在switch語句中,就像int,String。
  • Enum有自己的名稱空間
  • Enum可以實作Java接口
  • 可以在Enum中定義構造器

1 . Enum的聲明,Enum可以聲明在一個類之外或者在類内部,但是不能在方法中。

// 外部聲明Enum
enum Color {
    RED,GREEN,BLUE;
}
public class Test
{
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
    }
}
           
//内部聲明Enum
public class Test
{
    enum Color
    {
        RED, GREEN, BLUE;
    }
    
    public static void main(String[] args)
    {
        Color c1 = Color.RED;
        System.out.println(c1);
    }
}
           

2 . 在建立Enum常量的時候可以指定值,但是這個時候你需要定義一個成員變量構造器。構造器必須是private的,不然會報編譯錯誤。

public enum Currency {
    PENNY(1), NICKLE(5), DIME(10), QUARTER(25);
    private int value;

    private Currency(int value) {
        this.value = value;
    }
}
           

3 . 使用

==

equals

比較兩個enum

因為enum對象都是繼承自Enum類的,可以看到Enum中的equals方法為。

建議使用

==

方法,直接比較應該比調用方法的速度更快一些。另外

==

号還能防止

NullPointerException

public final boolean equals(Object other) {
        return this==other;
    }

           

4 . 對Enum進行排序的時候,使用compareTo方法。

public final int compareTo(E o) {
        Enum<?> other = (Enum<?>)o;
        Enum<E> self = this;
        if (self.getClass() != other.getClass() && // optimization
            self.getDeclaringClass() != other.getDeclaringClass())
            throw new ClassCastException();
        return self.ordinal - other.ordinal;
    }

           

5 .有兩個新的集合類

EnumMap

EnumSet

,他們兩個是對Set和Map的高性能實作,當有機會使用它們的時候,盡量使用它們。

Enum面試問題

  1. 說說Enum的繼承

    所有的enums隐式的extend了java.lang.Enum類,因為一個類隻能extend一個父親,是以enum不能extend其它的類。

    但是Enum可以實作許多接口

  2. Enum的values,ordinal,valueOf方法

    enums預設有values(),ordinal()和valueOf()方法。

    values()方法傳回所有在enum中定義的常量值,以數組形式傳回。

    ordinal()方法傳回每個常量的索引下标,就像數組的下标

    valueOf()方法傳入字元串參數,如果enum中存在對應字元串的常量值,則傳回對應的enum常量

// 案例代碼
enum Color
{
    RED, GREEN, BLUE;
}

public class EnumLearn
{
    public static void main(String[] args)
    {
        
        Color arr[] = Color.values();        
        for (Color col : arr)
        {
            System.out.println(col + " at index "
                    + col.ordinal());
        }
        System.out.println(Color.valueOf("RED"));
    }
}

//輸出
RED at index 0
GREEN at index 1
BLUE at index 2
RED
           

3 . Enum的構造器特性

enum可以有構造器方法,它的構造器方法會在enum類型加載的時候,按常量的個數順序的執行

我們不能直接建立enum對象,是以我們也不能直接調用enum的構造器方法,構造器方法必須是private的

//案例代碼
enum AccountType implements Serializable,Cloneable
{
    SAVING, FIXED, CURRENT;
    private AccountType()
    {
        System.out.println("It is a account type");
    }
}
class EnumOne
{
    public static void main(String[]args)
    {
        System.out.println(AccountType.FIXED);

    }
}
//輸出結果
It is a account type
It is a account type
It is a account type
FIXED
           

4 . Enum的單例模式優缺點

參考《Effitive Java》,優點大于缺點,因為enum是線程安全的,是以我們無需考慮單例模式的雙重檢查。主要原因:

  • enum的單例模式簡單
  • enum是線程安全的
  • enum的單例模式自己處理序列化 *
// Enum的單例模式 VS 傳統雙重檢查的單例模式
//單例模式,僅需使用一行代碼.
// EasySingleton.INSTANCE,enum中也可以寫其他方法
public enum EasySingleton{
    INSTANCE;
}

//傳統模式
public class DoubleCheckedLockingSingleton{
     private volatile DoubleCheckedLockingSingleton INSTANCE;
  
     private DoubleCheckedLockingSingleton(){}
  
     public DoubleCheckedLockingSingleton getInstance(){
         if(INSTANCE == null){
            synchronized(DoubleCheckedLockingSingleton.class){
                //  二次檢查
                if(INSTANCE == null){
                    INSTANCE = new DoubleCheckedLockingSingleton();
                }
            }
         }
         return INSTANCE;
     }
}

           

5 . Enum的

==

equals

的差別。

前面有提到。

6 . 我們能使用構造方法建立enum執行個體嗎?

不能,enum的構造方法必須是私有的。

Enum的用法建議

在能想到使用Enum的時候可以考慮使用Enum。

  1. 使用Enum代替定義的相關int類型常量
  2. 能用到EnumSet和EnumMap的時候使用它們,後面會再說明它們兩個的用法
  3. 表示固有的對象最好使用Enum

最後

看一些Java相關的面試題,發現Enum相關問題出現頻率挺高的,在這裡對enum用法做個整理。希望能幫助到大家

參考