Java 枚舉類
本小節我們將一起學習 Java 枚舉類,將涉及到什么是枚舉類、為什么需要枚舉類,如何自定義枚舉類以及如何使用枚舉類,Enum 類的常用方法等內容。理解為什么需要枚舉類以及學會自定義枚舉類是本小節學習的重點。
1. 什么是枚舉類
在數學和計算機科學中,一個集的枚舉是列出某些有窮序列集的所有成員的程序,或者是一種特定類型對象的技術。
枚舉是一個被命名的整型常數的集合。枚舉在生活中非常常見,列舉如下:
- 表示星期幾:
SUNDAY
、MONDAY
、TUESTDAY
、WEDNESDAY
、THURSDAY
、FRIDAY
、SATURDAY
就是一個枚舉; - 性別:
MALE
(男)、FEMALE
(女)也是一個枚舉; - 訂單的狀態:
PAIDED
(已付款)、UNPAIDED
(未付款)、FINISHED
(已完成),CANCELED
(已取消)。
知道了什么是枚舉,我們就很容易理解什么是枚舉類了,簡單來說,枚舉類就是一個可以表示枚舉的類,當一個類的對象只有有限個、確定個的時候,我們就可以定義一個枚舉類來存放這些對象。
2. 為什么需要枚舉類
如果不使用枚舉類,我們想在一個類中定義星期一到星期天,就可能需要在類中使用常量來表示,實例如下:
public class Weekday {
public static final int MONDAY = 1;
public static final int TUESDAY = 2;
public static final int WEDNESDAY = 3;
public static final int THURSDAY = 4;
public static final int FRIDAY = 5;
public static final int SATURDAY = 6;
public static final int SUNDAY = 7;
}
使用一組常量表示一個枚舉的集合,存在一個問題,編譯器無法檢測每個值的范圍是否合法,例如:
int day = 0; // 假設 day 的值為 0
if (day == Weekday.MON) {
System.out.println("今天星期一");
}
顯然,0 不在這些常量值所表示的范圍(1~7)內,但編譯器不會給出提示,這樣的編碼是非常不推薦的。
當我們在開發中需要定義一組常量的時候,建議使用枚舉類。接下來我們就來看如何定義枚舉類。
3. 如何自定義枚舉類
自定義枚舉類有兩種方式:
- 在 Java 5.0 之前,需要通過普通 Java 類的“改裝”來定義一個枚舉類;
- 在 Java 5.0 之后,可以使用
enum
關鍵字來定義枚舉類。
下面我們分別來看下這兩種定義枚舉類的方式。
3.1 Java 5.0 之前自定義枚舉類
在 Java 5.0之前,想要定義一個枚舉類較為繁瑣,通常需要以下幾個步驟:
- 定義一個 Java 普通類作為枚舉類,定義枚舉類的屬性,使用
private final
修飾; - 該類不提供外部實例化操作,因此將構造方法設置為私有,并初始化屬性;
- 在類內部,提供當前枚舉類的多個對象 ,使用
public static final
修飾; - 提供常用的
getter
、setter
或toString()
方法。
下面我們定義一個用于表示性別的枚舉類,并演示如何調用此枚舉類,其具體實例如下:
/**
* @author colorful@TaleLin
*/
public class EnumDemo1 {
/**
* 性別枚舉類
*/
static class Sex {
// 定義常量
private final String sexName;
// 私有化構造器,不提供外部實例化
private Sex(String sexName) {
// 在構造器中為屬性賦值
this.sexName = sexName;
}
public static final Sex MALE = new Sex("男");
public static final Sex FEMALE = new Sex("女");
public static final Sex UNKNOWN = new Sex("保密");
/**
* getter
*/
public String getSexName() {
return sexName;
}
/**
* 重寫toString方法,方便外部打印調試
*/
@Override
public String toString() {
return "Sex{" +
"sexName='" + sexName + '\'' +
'}';
}
}
public static void main(String[] args) {
System.out.println(Sex.FEMALE.getSexName());
System.out.println(Sex.MALE.getSexName());
System.out.println(Sex.UNKNOWN.getSexName());
}
}
運行結果:
女
男
保密
3.2 Java 5.0 之后自定義枚舉類
在 Java 5.0 后,可以使用eunm
關鍵字來定義一個枚舉類,比較便捷,推薦大家使用這個方法來定義枚舉類。
通常需要以下幾個步驟:
- 使用
enum
關鍵字定義枚舉類,這個類隱式繼承自java.lang.Enum
類; - 在枚舉類內部,提供當前枚舉類的多個對象,多個對象之間使用逗號分割,最后一個對象使用分號結尾;
- 聲明枚舉類的屬性和構造方法,在構造方法中為屬性賦值;
- 提供
getter
方法,由于Enum
類重寫了toString()
方法,因此一般不需要我們自己來重寫。
具體實例如下:
/**
* @author colorful@TaleLin
*/
public class EnumDemo2 {
public static void main(String[] args) {
Sex male = Sex.MALE;
// 打印 Sex 對象
System.out.println(male);
// 打印 getter方法的值
System.out.println(male.getSexName());
System.out.println(Sex.FEMALE.getSexName());
System.out.println(Sex.UNKNOWN.getSexName());
}
}
/**
* 使用 enum 關鍵字定義枚舉類,默認繼承自 Enum 類
*/
enum Sex {
// 1.提供當前枚舉類的多個對象,多個對象之間使用逗號分割,最后一個對象使用分號結尾
MALE("男"),
FEMALE("女"),
UNKNOWN("保密");
/**
* 2.聲明枚舉類的屬性
*/
private final String sexName;
/**
* 3.編寫構造方法,為屬性賦值
*/
Sex(String sexName) {
this.sexName = sexName;
}
/**
* 4.提供getter
*/
public String getSexName() {
return sexName;
}
}
運行結果:
MALE
男
女
保密
4. Enum 類
java.lang.Enum
類 是 Java 語言枚舉類型的公共基類,我們使用enum
關鍵字定義的枚舉類,是隱式繼承自Enum
類的,下面我們來看一下Enum
類的常用方法:
values()
:返回枚舉類型的對象數組。改方法可以很方便的遍歷所有的枚舉值;valueOf()
:可以把一個字符串轉換為對應的枚舉類對象。要求字符串必須是枚舉類對象的“名字”,如果不是,會拋出IllegalArguementException
;toString()
:返回當前枚舉類對象常量的名稱。
這 3 個方法使用起來比較簡單,因此我們寫在一個實例中,代碼如下:
/**
* @author colorful@TaleLin
*/
public class EnumDemo3 {
public static void main(String[] args) {
Sex male = Sex.MALE;
System.out.println("調用 toString() 方法:");
System.out.println(male.toString());
System.out.println("調用 values() 方法:");
Sex[] values = Sex.values();
for (Sex value : values) {
System.out.println(value);
}
System.out.println("調用 valueOf() 方法:");
Sex male1 = Sex.valueOf("MALE");
System.out.println(male1);
}
}
/**
* 使用 enum 關鍵字定義枚舉類,默認繼承自 Enum 類
*/
enum Sex {
// 1.提供當前枚舉類的多個對象,多個對象之間使用逗號分割,最后一個對象使用分號結尾
MALE("男"),
FEMALE("女"),
UNKNOWN("保密");
/**
* 2.聲明枚舉類的屬性
*/
private final String sexName;
/**
* 3.編寫構造方法,為屬性賦值
*/
Sex(String sexName) {
this.sexName = sexName;
}
// 提供 getter 和 setter
public String getSexName() {
return sexName;
}
}
運行結果:
調用 toString() 方法:
MALE
調用 values() 方法:
MALE
FEMALE
UNKNOWN
調用 valueOf() 方法:
MALE
值得注意的是,當調用valuOf()
方法時,我們傳遞的對象的“名字”,在枚舉類中并不存在,此時會拋出運行時異常:IllegalArgumentException
,實例如下:
/**
* @author colorful@TaleLin
*/
public class EnumDemo3 {
public static void main(String[] args) {
System.out.println("調用 valueOf() 方法:");
Sex male1 = Sex.valueOf("MALE1");
System.out.println(male1);
}
}
/**
* 使用 enum 關鍵字定義枚舉類,默認繼承自 Enum 類
*/
enum Sex {
// 1.提供當前枚舉類的多個對象,多個對象之間使用逗號分割,最后一個對象使用分號結尾
MALE("男"),
FEMALE("女"),
UNKNOWN("保密");
/**
* 2.聲明枚舉類的屬性
*/
private final String sexName;
/**
* 3.編寫構造方法,為屬性賦值
*/
Sex(String sexName) {
this.sexName = sexName;
}
// 提供 getter 和 setter
public String getSexName() {
return sexName;
}
}
運行結果:
調用 valueOf() 方法:
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant Sex.MALE1
at java.base/java.lang.Enum.valueOf(Enum.java:273)
at Sex.valueOf(EnumDemo3.java:17)
at EnumDemo3.main(EnumDemo3.java:8)
5. 小結
通過本小節的學習,我們知道了枚舉類就是一個可以表示枚舉的類,當一個類的對象只有有限個、確定個的時候,我們就可以定義一個枚舉類來存放這些對象。使用枚舉類可以規避編譯器無法檢測每個值的范圍是否合法的問題。自定義枚舉類可以有兩種方式,更推薦使用enum
關鍵字來定義枚舉類。所有通過enum
關鍵字定義的枚舉類都繼承自java.lang.Enum
類,要了解該類的常用方法的使用。