每天10點學習兩小時的我又:咕咕了🕊...
本人學習主要來源於尚硅谷
枚舉 enum
什么是枚舉類:
Java 枚舉是一個特殊的類,一般表示一組常量
-
比如: 一年的 4 個季節,一個年的 12 個月份,一個星期的 7 天,方向有東南西北等...
-
類似這種當一個變量有幾種固定可能的取值時, 可以將它定義為枚舉類型
出現:
-
Java1.5 之前是沒有
枚舉
和注解
的. -
那時候一般用接口常量來替代
而使用 Java 枚舉類型 enum 可以更貼近地表示這種常量.
還可以配合 Switch使用...
枚舉類的實現:
-
JDK1.5 之前需要自定義枚舉類.
-
JDK 1.5 新增的
enum
關鍵字用於定義枚舉類. -
若枚舉只有一個對象, 則可以作為一種單例模式的實現方式.
1.5之前 自定義實現枚舉類:
-
私有化類的構造器,保證不能在類的外部創建其對象
-
在類的內部創建枚舉類的實例,聲明為:
public static final
確保對象不會更改~ -
對象如果有實例變量,應該聲明為:
private final
通過構造器初始化
SeasonTest1.Java
Season.Java
package com.wsm;
/**
* 自定義枚舉類學習 Season季節: 一年有四個季節是固定是剛好用來做枚舉類
*/
public class SeasonTest1 {
public static void main(String[] args) {
//春天
Season chu = Season.SPRING;
System.out.println(chu.toString());
/**
* ok,這就是自定義枚舉類, 類的對象是有固定個數的!且不可更改, 救像一種規則固定的對象...
* 常用於規則狀態的定義: 商品: 缺貨 代發貨 待付款...等固定的狀態;
* */
}
}
class Season{
//1.私有化類的構造器,並給對象屬性賦值: 如果有對象屬性的話順便給屬性賦值~
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//2.聲明Season對象的屬性:private final修飾,因為枚舉對象是固定的不能更改的.
private final String seasonName;
private final String seasonDesc;
//3.創建當前類的 固定數量的對象(一年四季): public static final的
//因為是私有的構造函數,類中進行創建... 如果枚舉類只有一個對象,則就是一種單例模式! `餓漢式`
public static final Season SPRING = new Season("春天","春暖花開");
public static final Season SUMMER = new Season("夏天","夏日炎炎");
public static final Season AUTUMN = new Season("秋天","秋高氣爽");
public static final Season WINTER = new Season("冬天","冰天雪地");
//ok,到這兒,自定義的枚舉類就創建好了
//如果還有其它需求可以進行擴展... 創建方法:
/** 獲取枚舉類對象的屬性 */
/** 常量只有get(); 方法 */
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
/** toString()方法 */
public String toString() {
return "Season{" +
"seasonName='" + seasonName + '\'' +
", seasonDesc='" + seasonDesc + '\'' +
'}';
}
}
-
JDK5 之前, 的枚舉類需要通過改方法進行自定義~
Java中被 Final修飾的變量的幾種賦值方式
-
Final 表示"最后的、最終的"含義,變量一旦賦值后,不能被重新賦值
-
被 Final 修飾的實例變量必須顯式指定初始值
-
Final 修飾符通常和 static 修飾符一起使用來創建類常量
非靜態Final賦值有三種:定義初始化、非靜態代碼塊、構造方法
/*定義初始化時進行賦值
在聲明對象時直接賦值,賦值后就不可變了,這種是最容易想到的
*/
public class FinalTest {
private final Integer num = 10;
}
/*代碼塊中賦值
這種是在定義之初不進行賦值操作,而是在代碼塊中進行賦值,也是可以的
構造塊會在創建對象時被調用,每次創建時都會被調用,優先於類構造函數執行.
*/
public class FinalTest {
private final Integer num;
{
num = 10;
}
}
/*
構造器中賦值
在創建對象時進行賦值,一旦對象創建完成,就不可變了,所以在創建完對象后set()方法是不能進行賦值的
*/
public class FinalTest {
private final Integer num;
public FinalTest(Integer num) {
this.num = num;
}
}
靜態使用Final:static final
-
static final賦值有兩種:定義初始化、靜態代碼塊
/* 定義初始化 */
public class FinalTest {
private static final Integer num = 10 ;
}
/* 靜態代碼塊
用static{}包裹起來的代碼片段,只會執行一次 靜態代碼塊優先於構造塊執行.
*/
public class FinalTest {
private static final Integer num;
static {
num = 10;
}
}
enum 關鍵字實現枚舉類:
-
enum 定義的枚舉類默認繼承了
Java.lang.Enum
類:因此不能再 extends 繼承其他類
但可以 implements -
枚舉類的構造器只能使用 private 權限修飾符
-
必須在枚舉類的第一行聲明枚舉類對象
JDK 1.5 中可以在 switch 表達式中使用Enum定義的枚舉類的對象 作為表達式
case 子句可以直接使用枚舉值的名字(無需添加枚舉類作為限定)
SeasonTest2.Java
Season.Java
package com.wsm.two;
import javax.sound.midi.Soundbank;
/***
* JDK1.5 新增enum
*/
public class SeasonTest2 {
public static void main(String[] args) {
/** 秋天 */
Season AUTUMN = Season.AUTUMN;
System.out.println(AUTUMN); //嘗試注釋 toString()方法輸出: AUTUMN (對象名)
//enum extends Java.lang.enum類
/** enum常用方法 */
//values()方法:
// 返回枚舉類型的對象數組。該方法可以很方便地遍歷所有的枚舉值
//valueOf(String str)
// 可以把一個字符串轉為對應的枚舉類對象。要求字符串必須是枚舉類對象的“名字”。如不是,會有運行時異常:IllegalArgumentException。
//toString() 返回當前枚舉類對象常量的名稱
/** values() */
System.out.println("enum常用方法values()");
Season[] values = Season.values(); //返回該enum 的所有對象
//遍歷結果集
for (Season value : values) {
System.out.println(value);
}
/** valueOf(String str) */
System.out.println("enum常用方法valueOf(String str)");
Season winter = Season.valueOf("WINTER"); //根據固定對象名,返回對應的enum
System.out.println(winter);
/** switch用法
* 判斷對象屬於那一個...
* */
System.out.println("enum switch用法");
switch (winter){
case SPRING:
System.out.println("春");
break;
case SUMMER:
System.out.println("夏");
break;
case AUTUMN:
System.out.println("秋");
break;
case WINTER:
System.out.println("冬");
break;
default:
System.out.println("沒有匹配!");
}
}
}
/** 可以於自定義枚舉進行比較查看~ */
enum Season{
//1.必須在枚舉類的第一行聲明枚舉類對象
//枚舉類的所有實例必須在枚舉類中顯式列出(, 分隔 ; 結尾)
//因為枚舉,本機不可修改由類訪問可以取消: public static final 類
// public static final Season SPRING = new Season("春天","春暖花開");
SPRING("春天","春暖花開"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高氣爽"),
WINTER("冬天","冰天雪地");
//2.聲明Season對象的屬性:private final修飾
private final String seasonName;
private final String seasonDesc;
//3.私有化類的構造器,並給對象屬性賦值
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//擴展方法
/** get */
public String getSeasonName() {
return seasonName;
}
public String getSeasonDesc() {
return seasonDesc;
}
/** toString
* 注釋方法直接輸出發現,即使不重新toString(); 也不是打印對象的: 地址值(棧指向堆的地址!)
* 因為: enum類,是繼承於 Java.lang.enum的,而不是 Object類
* */
// @Override
// public String toString() {
// return "Season{" +
// "seasonName='" + seasonName + '\'' +
// ", seasonDesc='" + seasonDesc + '\'' +
// '}';
// }
}
enum 常用方法
方法名稱 | 描述 |
---|---|
values() | 以數組形式返回枚舉類型的所有成員 |
valueOf( String ) | 將普通字符串轉換為枚舉實例 |
compareTo() | 比較兩個枚舉成員在定義時的順序 |
ordinal() | 獲取枚舉成員的索引位置 |
enum 高級:implements實現類
-
enum 類繼承了
java.lang.enum類
Java單根性所以不能在繼承, 但Java 可以多實現
-
eunm 類 還可以 實現接口...達到擴展的方式
實現方式:
-
正常實現,重寫方法....
但這樣所有的對象, 方法實現都一樣!
SeasonTest3
Season
Info
public class SeasonTest3 {
public static void main(String[] args) {
Season autumn = Season.AUTUMN;
autumn.show();
}
}
//使用enum關鍵字枚舉類 implements 實現接口,重寫show()方法~
enum Season implements Info{
SPRING("春天","春暖花開"),
SUMMER("夏天","夏日炎炎"),
AUTUMN("秋天","秋高氣爽"),
WINTER("冬天","冰天雪地");
//2.聲明Season對象的屬性:private final修飾
private final String seasonName;
private final String seasonDesc;
//3.私有化類的構造器,並給對象屬性賦值
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
//重寫接口的方法!
public void show() {
System.out.println("這是一個季節~");
}
}
/** 接口 */
interface Info{
void show();
} -
給每個enum 對象,來一個特有的固定實現!
public class SeasonTest4 {
public static void main(String[] args) {
Season autumn = Season.AUTUMN;
autumn.show();
}
}
//使用enum關鍵字枚舉類 implements 實現接口,重寫show()方法~
enum Season implements Info {
SPRING("春天","春暖花開"){
public void show() { System.out.println("春天在哪里?"); }
},
SUMMER("夏天","夏日炎炎"){
public void show() { System.out.println("寧夏"); }
},
AUTUMN("秋天","秋高氣爽"){
public void show() { System.out.println("秋天不回來"); }
},
WINTER("冬天","冰天雪地"){
public void show() { System.out.println("大約在冬季"); }
};
//2.聲明Season對象的屬性:private final修飾
private final String seasonName;
private final String seasonDesc;
//3.私有化類的構造器,並給對象屬性賦值
private Season(String seasonName,String seasonDesc){
this.seasonName = seasonName;
this.seasonDesc = seasonDesc;
}
}
/** 接口 */
interface Info{
void show();
}
枚舉集合
在 Java 語言中和枚舉類相關的,還有兩個枚舉集合類java.util.EnumSet
和 java.util.EnumMap
使用 EnumSet
可以保證元素不重復,並且能獲取指定范圍內的元素
public class EnumTest {
public static void main(String[] args) {
List<ErrorCodeEnum> list = new ArrayList<ErrorCodeEnum>();
list.add(ErrorCodeEnum.SUCCESS);
list.add(ErrorCodeEnum.SUCCESS); //重復元素
list.add(ErrorCodeEnum.SYS_ERROR);
list.add(ErrorCodeEnum.NAMESPACE_NOT_FOUND);
// 去掉重復數據
EnumSet<ErrorCodeEnum> enumSet = EnumSet.copyOf(list);
System.out.println("去重:" + enumSet);
// 獲取指定范圍的枚舉(獲取所有的失敗狀態)
EnumSet<ErrorCodeEnum> errorCodeEnums = EnumSet.range(ErrorCodeEnum.ERROR, ErrorCodeEnum.UNKNOWN_ERROR);
System.out.println("所有失敗狀態:" + errorCodeEnums);
}
}
enum ErrorCodeEnum {
SUCCESS(1000, "success"),
ERROR(2001, "parameter error"),
SYS_ERROR(2002, "system error"),
NAMESPACE_NOT_FOUND(2003, "namespace not found"),
NODE_NOT_EXIST(3002, "node not exist"),
NODE_ALREADY_EXIST(3003, "node already exist"),
UNKNOWN_ERROR(9999, "unknown error");
private int code;
private String msg;
ErrorCodeEnum(int code, String msg) {
this.code = code;
this.msg = msg;
}
public int code() { return code; }
public String msg() { return msg; }
}
-
EnumMap
與HashMap
類似,不過它是一個專門為枚舉設計的Map
集合 -
相比
HashMap
來說它的性能更高,因為它內部放棄使用鏈表和紅黑樹的結構,采用數組作為數據存儲的結構-
以枚舉作為 key,查詢直接找到對應的
數組下標
快速定位元素EnumMap<枚舉對象,Object>
-
為什么使用枚舉?😕
更強的類型約束
-
在枚舉沒有誕生之前,也就是 JDK 1.5 版本之前
-
我們通常會使用
int
常量來表示枚舉,用來區分,狀態類型: B站上傳視頻為例,視頻一般有三個狀態:草稿、審核和發布int
類型本身並不具備安全性,假如某個程序員在定義int
時少些了一個final
關鍵字,那么就會存在被其他人修改的風險,反觀枚舉類,它“天然”就是一個常量類,不存在被修改的風險。
使用
int
類型的語義不夠明確枚舉更加清晰表示一種狀態
單例模式:
-
使用枚舉實現
單例模式
更加簡單!
線程安全:
-
枚舉類最終會被編譯為被
final
修飾的普通類 -
它的所有屬性也都會被
static
和final
關鍵字修飾,所以枚舉類在項目啟動時就會被 JVM 加載並初始化且不允許更改!線程安全
方便比較:
-
枚舉比較時使用 == 就夠了,因為枚舉類是在程序加載時就創建了(它並不是
new
出來的)每個對象全局只有一個!
-
== 比較地址,相同對象的地址也相同!
ok, 枚舉就介紹到這兒了,晚安,集美門😘