Java面向對象之枚舉——enum

Java面向對象之枚舉——enum

Java面向對象之枚舉——enum

引出枚舉

首先來考慮這樣一個需求:判斷一個員工(Employee)在一週的哪一天休息。

解決方案:定義一個類Weekday來表示周1到週日,在類中分別使用7個常量來表示周1到週日,代碼如下:

<code>public class Employee {

\t// 休息日
\tprivate int restDay;
\t
\tpublic void setRestDay(int restDay) {
\t\tthis.restDay = restDay;
\t}
\t
\tpublic int getRestDay() {
\t\treturn restDay;
\t}

public void isRestDay() {
\tif (restDay == 6 || restDay == 7) {
System.out.println("今天是休息日");
} else {
\t\tSystem.out.println("今天不是休息日");
}
}

}/<code>
<code>public class WeekDay {

\tpublic static final int MONDAY = 1;
\tpublic static final int TUESDAY = 2;
\tpublic static final int WEDNESDAY = 3;
\tpublic static final int THURSDAY = 4;
\tpublic static final int FRIDAY = 5;
\tpublic static final int SATURDAY = 6;
\tpublic static final int SUNDAY = 7;


}/<code>

運行案例:

<code>public static void main(String[] args) {
\tEmployee employee = new Employee();
\temployee.setRestDay(WeekDay.SUNDAY);
\temployee.isRestDay();

}/<code>

此時,上述的代碼示例很清楚的解決了業務需求,引入的Weekday類很好的表示了從週一到週日。但是也存在一些問題,因為在Employee中的restDay的類型是int類型,我們依然可以隨意設置irestDay的值,代碼並不健壯,依然沒有解決數據類型不安全的問題,任然有改進的空間。


為了解決數據類型不安全的問題的問題,可以在WeekDay中引入私有構造器,防止WeekDay被除自身以外的其他對象實例化,然後可以將WeekDay作為休息日的數據類型,很好的解決了數據類型不安全的問題,同時,也可以將休息日的個數固定下來。改造後的代碼如下:

<code>public class Employee {

\t// 休息日
\tprivate WeekDay restDay;
\t
\tpublic void setRestDay(WeekDay restDay) {
\t\tthis.restDay = restDay;
\t}
\t

\tpublic WeekDay getRestDay() {
\t\treturn restDay;
\t}

public void isRestDay() {
\tif (restDay == WeekDay.SATURDAY || restDay == WeekDay.SUNDAY) {
System.out.println("今天是休息日");
} else {
\t\tSystem.out.println("今天不是休息日");
}
}

}/<code>


<code>public class WeekDay {
\tprivate WeekDay() {}
\tpublic static final WeekDay MONDAY = new WeekDay();
\tpublic static final WeekDay TUESDAY = new WeekDay();
\tpublic static final WeekDay WEDNESDAY = new WeekDay();
\tpublic static final WeekDay THURSDAY = new WeekDay();
\tpublic static final WeekDay FRIDAY = new WeekDay();
\tpublic static final WeekDay SATURDAY = new WeekDay();
\tpublic static final WeekDay SUNDAY = new WeekDay();

}/<code>


運行案例:

<code>public static void main(String[] args) {
\tEmployee employee = new Employee();
\temployee.setRestDay(WeekDay.SUNDAY);
\temployee.isRestDay();

}/<code>

到這裡,不僅業務需求明確,數據類型安全的問題也解決了。


Java 枚舉

從Java 5 開始,提供了一種新的數據類型,枚舉。和接口一樣,枚舉是一個特殊的類,其實質上就是數量固定的多個常量對象的集合。枚舉主要用來表示固定的事務類型。

枚舉語法定義格式:常量之間使用英文狀態下的“,”分隔,最後一個常量之後必須要用“;”結尾。

<code>[修飾符] enum 枚舉類名

{

常量A,常量B,常量C;

}/<code>

在上述案例中的WeekDay類用枚舉來重寫就是這樣的:

<code>enum  WeekDay {
\t\tMONDAY,TUESDAY,WEDNESDAY,THURSDAY ,FRIDAY,SATURDAY,SUNDAY;
}/<code>

在開發中自定義的枚舉類,在底層都是直接繼承於java.lang.Enum類的,Enum類是所有枚舉的父類。看下圖會有一個更直觀的感受:


Java面向對象之枚舉——enum

底層的枚舉類


枚舉特點:

  1. 枚舉的直接父類是java.lang.Enum,但和java.lang.Object一樣,枚舉都不會顯式地繼承Enum。
  2. 枚舉就相當於一個類,可以定義構造方法、成員變量、普通方法和抽象方法。
  3. 擁有默認的私有構造方法,即使不寫訪問權限也是private,因為枚舉在底層沒有無參數構造器的。
  4. 枚舉中的每個常量都是全局的,每個常量都是一個實例,且因為常量個數是固定的有限個的,所以實例個數也是固定的,且枚舉類不能使用new關鍵字。
  5. 枚舉實例必須位於枚舉結構體中的最開始部分,枚舉實例列表的最後必須要有分號與其他成員相分隔。
  6. 枚舉實例後有花括號時,該實例是枚舉類的匿名內部類對象。


枚舉的使用

1.枚舉中的常量都是全局公共的靜態常量,可以直接使用枚舉類名調用。

<code>Weekday day = Weekday.SATURDAY;/<code>

2.因為java.lang.Enum類是所有枚舉類的父類,所以所有的枚舉對象可以調用Enum類中的方法。

<code>String name = 枚舉對象.name();   // 返回枚舉對象的常量名稱

int ordinal = 枚舉對象.ordinal(); // 返回枚舉對象的序號,從0開始.

String str = 枚舉對象.toString(); // 返回 枚舉對象的常量名稱/<code>


3.JVM為枚舉類生成的靜態方法:

<code>1.枚舉類型[] values();

Weekday[] ws = Weekday.values();:返回當前枚舉類型所有的常量,使用一個數組封裝起來.


2.枚舉類型 valueof(String name);

Weekday day = Weekday.valueOf("MONDAY"); // 把一個指定名稱字符串轉換為當前枚舉類中同名的常量./<code>


4.從Java 5開始switch也支持操作枚舉類型。

雖然switch只支持int類型,但因為支持枚舉時在底層使用的枚舉常量的ordinal,而ordinal的類型依然是int類型。所以也可以說switch是在間接支持枚舉。

Java面向對象之枚舉——enum

switch支持枚舉


枚舉的單例模式

在<<effective>>書中提到,建議使用枚舉類做單例模式,能夠很好的保護代碼隱私,即使使用反射也不能創建對象。通過以下的兩種代碼對比,能夠很直觀的展現枚舉實現的單例模式:/<effective>


Java面向對象之枚舉——enum

未使用枚舉的單例模式


Java面向對象之枚舉——enum

使用枚舉的單例模式


完結。


分享到:


相關文章: