秒懂系列,超詳細Java枚舉教程!!!

所有知識體系文章,GitHub已收錄,歡迎Star!再次感謝,願你早日進入大廠!

GitHub地址: https://github.com/Ziphtracks/JavaLearningmanual

深入理解Java枚舉

一、什麼是枚舉

1.1 什麼是枚舉?

至於枚舉,我們先拿生活中的枚舉來入手,然後再引申Java中的枚舉,其實它們的意義很相似。

談到生活中的枚舉,假如我們在玩擲骰子的遊戲,在我們手中有兩個骰子,要求擲出兩個骰子的點數和必須大於6的概率,那麼在此情此景,我們就需要使用枚舉法一一列舉出骰子點數的所有可能,然後根據列舉出來的可能,求出概率。

可能有的小夥伴發現,這就是數學啊?這就是數學中的概率學和統計學。對,我們的枚舉法就是常用於概率統計中的。

1.2 Java中的枚舉類

Java 5.0引入了枚舉,枚舉限制變量只能是預先設定好的值。使用枚舉可以減少代碼中的 bug,方便很多場景使用。

二、Java枚舉的語法

枚舉類中的聲明

1訪問修辭符 enum 枚舉名 {
2    枚舉成員,
3    枚舉成員,
4    ...
5};

class類中枚舉的聲明

1訪問修飾符 class 類名 {
2    enum 枚舉名 {
3        枚舉成員,
4        枚舉成員,
5        ...
6    }
7}

三、Java枚舉類的使用規則和應用場景

3.1 Java枚舉類的使用規則

至於枚舉你也有所了解了,Java中的枚舉也是一樣的。而Java中枚舉類的使用,也有特定的規則和場景。如果你看了以下的規則不明白的話,沒有關係,繼續向下學你就會明白,因為我在下面都會有講解到這些規則。如下幾個規則:

  • 類的對象是確定的有限個數。
  • 當需要定義一組常量時,建議使用枚舉。
  • 如果枚舉類中只有一個對象,則可以作為單例模式的實現方法。
  • 枚舉類不能被繼承
  • 枚舉類不能被單獨的new創建對象
  • 枚舉類中的枚舉成員是用`,`隔開的,多個枚舉成員之間用`_`隔開
  • 如果枚舉類中的只有一個或多個枚舉成員,其他什麼都沒有,我們在用`,`隔開的同時。最後可以省略`;`結束符。

注意: 如果關於枚舉單例設計模式不太了解的小夥伴可以參考深度學習單例設計模式一文,你肯定會有意想不到收穫,請相信我!

3.2 Java枚舉類的應用場景

根據Java中使用枚舉類的規則,有以下幾種場景適合來使用枚舉類,如下:

  • 星期: Monday(星期一)、Tuesday(星期二)、Wednesday(星期三)、Thursday(星期四)、Firday(星期五)、Saturday(星期六)、Sunday(星期日)
  • 性別: Man(男)、Woman(女)
  • 季節: Spring(春天)、Summer(夏天)、Autumn(秋天)、Winter(冬天)
  • 支付方式: Cash(現金)、WeChatPay(微信)、Alipay(支付寶)、BankCard(銀行卡)、CreditCard(信用卡)
  • 訂單狀態: Nonpayment(未付款)、Paid(已付款)、Fulfilled(已配貨)、Delivered(已發貨)、Return(退貨)、Checked(已確認)
  • 線程狀態: Establish(創建)、Ready(就緒)、Run(運行)、Obstruct(阻塞)、Die(死亡)
  • 等等……

四、枚舉類的基本使用步驟解析

那我們就解釋以下這兩個規則,我們在上述中已經了解了枚舉的作用。Java中枚舉也不例外,也是一一列舉出來方便我們拿出來一個或多個使用。這有點像我們的多選框,我們把需要用到的所有選項內容放在各個多選框後面,當我們在使用的時候只需要勾選自己需要的勾選框即可,這就代表了我們需要被選中多選框後面的內容。

那麼,Java中的枚舉類是如何使用呢?

這裏我們簡單的模擬一個場景,假設你的女朋友十分的喜歡喝點冷飲或熱奶茶之類的飲品,在生活中也有很多像蜜雪冰城等等這種類型的飲品店。當你為女朋友買她愛喝的珍珠奶茶時,服務員會問你,要大杯、中杯還是小杯的。當然,為了滿足女朋友,你通常會選擇大杯。這就意味着店內不允許顧客點規則外的飲品。

注意: 如果你是初學者或是不了解枚舉類的使用,此基本使用不懂沒有關係,請繼續往下看即可!

於是,我用Java代碼來實現一下,上述場景。

首先,創建枚舉類。分別為珍珠奶茶添加大、中、小杯杯型。

 1package com.mylifes1110.java;
2
3/**
4 * @ClassName PearlMilkTea
5 * @Description 為珍珠奶茶添加三個杯型:大、中、小
6 * @Author Ziph
7 * @Date 2020/6/8
8 * @Since 1.8
9 */

10public enum PearlMilkTea {
11    //注意:這裏枚舉類中只有枚舉成員,我在此省略了;結束符
12    SMALL, MEDIUM, LARGE
13}

其次,創建珍珠奶茶對象,再有方法來判斷枚舉類中的大、中、小杯。最後打印女朋友喝哪個杯型的珍珠奶茶!

 1package com.mylifes1110.test;
2
3import com.mylifes1110.java.PearlMilkTea;
4
5/**
6 * @ClassName PearlMilkTeaTest
7 * @Description 為女朋友買哪個杯型的珍珠奶茶(默認大杯)
8 * @Author Ziph
9 * @Date 2020/6/8
10 * @Since 1.8
11 */

12public class PearlMilkTeaTest {
13    public static void main(String[] args) {
14        //創建大杯的珍珠奶茶對象
15        PearlMilkTea pearlMilkTea = PearlMilkTea.LARGE;
16        PearlMilkTeaTest.drinkSize(pearlMilkTea);
17    }
18
19    //判斷為女朋友買哪個杯型的珍珠奶茶
20    public static void drinkSize(PearlMilkTea pearlMilkTea) {
21        if (pearlMilkTea == PearlMilkTea.LARGE) {
22            System.out.println("我為女朋友買了一大杯珍珠奶茶!");
23        } else if (pearlMilkTea == PearlMilkTea.MEDIUM) {
24            System.out.println("我為女朋友買了一中杯珍珠奶茶!");
25        } else {
26            System.out.println("我為女朋友買了一小杯珍珠奶茶!");
27        }
28    }
29}

image-20200608151052517

雖然,我們了解了枚舉類中的基本使用,但是我們在語法中還介紹了一種在類中定義的枚舉。正好,在此也演示一下。如下:

1public class PearlMilkTea {
2    enum DrinkSize {
3        SMALL,
4        MEDIUM, 
5        LARGE
6    }
7}

如果這樣創建就可以在class類中去創建enum枚舉類了。想想前面例子中的代碼其實並不合理,這是為什麼呢?因為我們寫代碼要遵循單一職責原則和見命知意的命名規範。所以,我寫的代碼是在珍珠奶茶的枚舉類中列舉的大、中、小的三種杯型枚舉成員。所以根據規範來講,我們珍珠奶茶中不能擁有杯型相關的枚舉,畢竟我們在生活中的這類飲品店中喝的所有飲品種類都有這三種杯型,因此我們的所有飲品種類中都需要寫一個枚舉類,顯然這是很不合理的。

如果讓它變的更加合理化,我們就細分飲品種類來創建飲品枚舉類和杯型的枚舉類並分別兩兩適用即可。也許有小夥伴會問我為什麼我要說這些合理不合理呢?因為自我感覺這是對枚舉類應用的思想鋪墊,所以你品、你細品!

五、自定義枚舉類

5.1 自定義枚舉類步驟

關於第四章枚舉類的基本使用,也許小夥伴們對枚舉的陌生,而並不知道為什麼這樣去創建枚舉對象。接下來,我來帶你使用常量來自定義枚舉類,試試是不是那個效果。

既然,上述第三章我舉出了這麼多枚舉類的應用場景,那我們挑選一個比較經典的春夏秋冬來實現自定義枚舉類。

首先,我們先創建一個季節類,分別提供屬性、私有構造器、春夏秋冬常量、Getter方法和toString方法,步驟如下:

 1package com.mylifes1110.java;
2
3/**
4 * 自定義季節的枚舉類
5 */

6public class Season {
7    //聲明Season對象的屬性,為private final修飾
8    private final String seasonName;
9
10    //私有化構造器,併為對象賦值
11    private Season(String seasonName) {
12        this.seasonName = seasonName;
13    }
14
15    //提供當前枚舉的多個對象,為public static final修飾
16    public static final Season SPRING = new Season("春天");
17    public static final Season SUMMER = new Season("夏天");
18    public static final Season AUTUMN = new Season("秋天");
19    public static final Season WINTER = new Season("冬天");
20
21    //提供外界通過getter方法來獲取枚舉對象的屬性
22    public String getSeasonName() {
23        return seasonName;
24    }
25
26    //重寫toString方法,以便打印出枚舉結果
27    @Override
28    public String toString() {
29        return "Season{" +
30                "seasonName='" + seasonName + '\'' +
31                '}';
32    }
33}

其次,我們去創建一個測試類,來使用該自定義枚舉類創建對象。由此看來,我們就可以根據類名來句點出常量對象了!

 1package com.mylifes1110.test;
2
3import com.mylifes1110.java.Season;
4
5/**
6 * 測試類
7 */

8public class SeasonTest {
9    public static void main(String[] args) {
10        Season spring = Season.SPRING;
11        System.out.println(spring);
12    }
13}

最後打印結果是春天的對象,由於我們覆蓋了toString方法,即可見對象內的內容。

image-20200608160220000

5.2 使用帶有參枚舉類

如果你在第三章時Java枚舉類的基本使用不明白,估計看完自定義枚舉類也了解的大差不差了。但是你有沒有發現我們自定義枚舉類是使用的有參數的對象呢?那我們怎樣使用真正的枚舉類來實現有參數的枚舉類呢?繼續看吧那就!

在這裏我將自定義枚舉類改裝了一下,改裝成了enum枚舉類實現的使用有參對象。如下:

 1package com.mylifes1110.java;
2
3public enum Season {
4    SPRING("春天"),
5    SUMMER("夏天"),
6    AUTUMN("秋天"),
7    WINTER("冬天");
8
9    private final String seasonName;
10
11    Season1(String seasonName) {
12        this.seasonName = seasonName;
13    }
14
15    public String getSeasonName() {
16        return seasonName;
17    }
18}

不知道你有沒有發現少了點什麼,少的部分其實就是我們創建常量對象的部分,而且在這個枚舉類中我也沒有去重寫toString方法,至於為什麼,下面就告訴你。

注意: 枚舉對象之間用,隔開!

其次,去創建了該枚舉類的測試類,我們測試以下,並看一下沒有重寫toString方法打印出來的結果。

 1package com.mylifes1110.test;
2
3import com.mylifes1110.java.Season;
4
5public class Seaso1Test {
6    public static void main(String[] args) {
7        Season1 spring = Season.SPRING;
8        System.out.println(spring);                     //SPRING
9