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