Java enum枚舉在實際項目中的常用方法
- 2020 年 3 月 6 日
- 筆記
在項目實際開發過程中,經常會遇到對某些固定的值、字典項的定義的需求,很多項目經常使用常量來定義,其實在jdk1.5就已經引入了枚舉,使用枚舉可以更好的解決這類需求,本文主要記錄枚舉的優勢以及經常在項目中使用的方法。
知識點
- 枚舉類命名
枚舉類的命名通常需要Enum為後綴,枚舉成員名稱需要全大寫,單詞間用下劃線隔開。 - 枚舉類不允許使用 extends 關鍵字
枚舉類默認會繼承java.lang.Enum,由於java是單繼承,所以在定義枚舉類時不允許再繼承其他類,但可以實現多個介面 - 枚舉的比較可以直接使用 ==
枚舉是不允許被new出來的,枚舉類里的構造函數都限定為私有化,是不允許使用public定義構造函數的。枚舉的賦值,如果是同一個元素,則會指向同一個地址,所以是可以直接使用==的,當然在Enum類中,重寫了equals方法(如下圖),所以也是可以用equals來判斷。
- 枚舉常用方法
方法名 | 用途 |
---|---|
name() | 返回枚舉常量名 |
toString() | 返回枚舉常量名 |
values() | 返回枚舉成員數組 |
valueOf() | 通過枚舉常量名返回枚舉 |
ordinal() | 返回枚舉常量在enum聲明中的位置,位置是從0開始計數的 |
- 枚舉在switch中的使用
枚舉在switch中的使用,優勢在於能控制case的範圍(看以下實例),並且在idea中有相關提示 - 枚舉在單例模式的使用
首先使用枚舉類實現單例模式,寫法相當簡單,看最後的實例;其次枚舉是執行緒安全、單一實例(由於構造方法都是私有的,不能被new)
實例
1. 最簡單的枚舉
在項目中經常會遇到一些固定值的定義,以往都是用常量來定義,以下用實例說明,為啥枚舉的方式優於常量的方式,以下就以季節的定義為例
1.1 使用常量來實現
/** * @Description: 季節常量定義 */ public class SeasonConst { /** * 春季 */ public static final String SPRING = "SPRING"; /** * 夏季 */ public static final String SUMMER = "SUMMER"; /** * 秋季 */ public static final String AUTUMN = "AUTUMN"; /** * 冬季 */ public static final String WINTER = "WINTER"; }
以上實例雖然實現了功能,但有兩點比較明顯的缺點:
- 常量值容易寫錯(特別是複製黏貼,但是忘記改對應的值,導致系統出bug),idea不會給任何提示。
比如,某人粗心,在複製黏貼程式碼時變成(將春季、夏季都定義成春季了):
/** * 春季 */ public static final String SPRING = "SPRING"; /** * 夏季 */ public static final String SUMMER = "SPRING";
- 如果我想知道一年總共多少個季節,咋整?用常量定義的類,有點捉襟見肘
1.2 使用枚舉來實現,可以實現常量的所有功能,並能輕鬆解決以上提出的常量的兩個缺點
- 定義枚舉類SeasonEnum
public enum SeasonEnum { /** * 春季 */ SPRING, /** * 夏季 */ SUMMER, /** * 秋季 */ AUTUMN, /** * 冬季 */ WINTER }
在SeasonEnum枚舉類中,如果定義兩個 SPRING,編譯器會直接報錯,很好解決了常量的第一個缺點
- 該枚舉類的使用(1、獲取枚舉值的名稱;2、枚舉判斷的使用;3、枚舉循環的使用。通過枚舉的循環,很好解決了常量的第二個缺點;)
//獲取枚舉值的名稱,與toString得到的結果一樣 String spring = SeasonEnum.SPRING.name(); System.out.println(spring); //枚舉判斷的使用 SeasonEnum springEnum1 = SeasonEnum.SPRING; SeasonEnum springEnum2 = SeasonEnum.SPRING; SeasonEnum summerEnum3 = SeasonEnum.SUMMER; //由於springEnum1、springEnum2都指向SPRING,所以輸出true System.out.println("springEnum1 == springEnum2:" + (springEnum1 == springEnum2)); //由於springEnum1指向SPRING、summerEnum3指向SUMMER,所以輸出false System.out.println("springEnum1 == summerEnum3:" + (springEnum1 == summerEnum3)); //循環枚舉,列印枚舉類中的所有枚舉成員 SeasonEnum[] seasonEnums = SeasonEnum.values(); for (SeasonEnum seasonEnum : seasonEnums) { System.out.println(seasonEnum.name()); }
- 枚舉在switch中的使用,如果case後跟不存在SeasonEnum類中的枚舉(比如 case OTHER),則編譯器會報錯
String enumName = "SPRING"; SeasonEnum seasonEnum = SeasonEnum.valueOf(enumName); switch (seasonEnum){ case SPRING: System.out.println(seasonEnum.name()); break; case SUMMER: System.out.println(seasonEnum.name()); break; case AUTUMN: System.out.println(seasonEnum.name()); break; case WINTER: System.out.println(seasonEnum.name()); break; default: System.out.println("other"); }
2.在枚舉中使用自定義屬性和方法
項目中經常也會遇到一些字典項的定義,比如性別,包含存入資料庫中的值,以及顯示在頁面上的值。以下通過實例來實現性別字典。
- 定義SexEnum(注意看程式碼中的註解)
public enum SexEnum { MAN("man","男"), WOMEN("women","女"); private String sexCode; private String sexName; /** * 自定義構造函數,以完成枚舉對sexCode、sexName賦值 * @param sexCode * @param sexName */ SexEnum(String sexCode,String sexName){ this.sexCode = sexCode; this.sexName = sexName; } /** * 獲取sexCode * @return */ public String getSexCode() { return sexCode; } /** * 獲取sexName * @return */ public String getSexName() { return sexName; } /** * 項目中經常會根據code,轉換成對應的name * 所以這裡自定義方法,根據sexCode獲取sexName * 通過循環enum來實現 * @param sexCode * @return */ public static String getSexNameByCode(String sexCode){ String sexName = "sexCode不存在"; SexEnum[] sexEnums = SexEnum.values(); for (SexEnum sexEnum : sexEnums) { if(sexEnum.getSexCode().equals(sexCode)){ sexName = sexEnum.getSexName(); break; } } return sexName; } /** * 項目中也有根據name,轉換成對應的code * 所以這裡自定義方法,根據sexName獲取sexCode * 通過循環enum來實現 * @param sexName * @return */ public static String getSexCodeByName(String sexName){ String sexCode = "sexName不存在"; SexEnum[] sexEnums = SexEnum.values(); for (SexEnum sexEnum : sexEnums) { if(sexEnum.getSexName().equals(sexName)){ sexCode = sexEnum.getSexCode(); break; } } return sexCode; } /** * 根據sexCode獲取SexEnum,在switch中使用 * 通過循環enum來實現 * @param sexCode * @return */ public static SexEnum getEnumByCode(String sexCode){ SexEnum[] sexEnums = SexEnum.values(); for (SexEnum sexEnum : sexEnums) { if(sexEnum.getSexCode().equals(sexCode)){ return sexEnum; } } return null; } /** * 重寫toString方法 * @return */ @Override public String toString() { return this.sexCode + ":" + this.sexName; } }
- SexEnum枚舉類的使用
public class EnumMain { public static void main(String[] args){ //循環帶自定義方法的枚舉 SexEnum[] sexEnums = SexEnum.values(); for (SexEnum sexEnum : sexEnums) { System.out.println("sexCode:"+sexEnum.getSexCode()); System.out.println("sexName:"+sexEnum.getSexName()); System.out.println("sexCode:sexName="+sexEnum.toString()); } //根據sexCode獲取sexName String sexName = SexEnum.getSexNameByCode("women"); System.out.println("根據sexCode獲取sexName:" + sexName); //根據sexName獲取sexCode String sexCode = SexEnum.getSexCodeByName("男"); System.out.println("根據sexName獲取sexCode:" + sexCode); //通過傳入的sexCode使用switch testSexEnumSwitch("women"); } /** * 實際項目中,基本上都是傳sexCode的,所以這裡也根據傳入的sexCode,使用switch方法 * @param sexCode */ private static void testSexEnumSwitch(String sexCode){ //自定義getEnumByCode方法,通過sexCode獲取SexEnum SexEnum sexEnum = SexEnum.getEnumByCode(sexCode); switch (sexEnum){ case MAN: System.out.println(sexEnum.toString()); break; case WOMEN: System.out.println(sexEnum.toString()); break; default: System.out.println("other"); } } }
3.通過枚舉實現單例
- 單例定義
public enum Singleton { INSTALL; /** * 自定義方法 */ public void yourMethod(){ System.out.println("do your business"); } }
- 調用方法
Singleton.INSTALL.yourMethod();
源碼獲取
以上示例都可以通過我的GitHub獲取完整的程式碼,點擊獲取