再談java列舉enum

远洪發表於2024-10-13

一、認識列舉

列舉是一種特殊類

列舉的定義:

修飾符 enum 列舉名 {
       列舉項1,列舉項2,列舉項3;
       其他成員;
}

注意:

  • 列舉的第一行只能寫列舉項,多個列舉項用逗號(,),隔開
  • 每一個列舉項都是一個常量(不可改變值),且都指向一個該列舉的物件

二、為什麼要使用列舉

例如,有這麼一方法,需要獲取男孩和女孩的一些特徵。傳入男孩,就返回男孩的資訊,傳入女孩,就返回女孩的資訊。

我們來看以下幾種方法實現。

方法一

我們用1表示男孩,2表示女孩,程式碼如下:

package org.example.enumX;

public class Example2 {
    public static void main(String[] args) {
        choseStudent(1);
    }
    public static void choseStudent(int sex){
        switch (sex){
            case 1:
                System.out.println("男孩的特徵");
                break;
            case 2:
                System.out.println("女孩的特徵");
                break;
            default:
                System.out.println("引數錯誤");
        }
    }
}
// 程式輸出:男孩的特徵

以上程式碼雖然實現了業務邏輯,但是方法傳1和傳2並不能讓人很快理解該值的意思,甚至我們可以傳3,4,5,6,7 沒有任何限制。

為了讓程式碼更容易理解, 我們吧男孩和女孩封裝到一個類裡面,如下,方法二

方法二

同樣,用1表示男孩,2表示女孩,只是我們把資訊封裝到一個類裡面了。

package org.example.enumX;
class StudentA{
    public static final int boy = 1;
    public static final int girl = 2;
}

public class Example1 {
    public static void main(String[] args) {
        choseStudent(StudentA.boy);
    }
    public static void choseStudent(int sex){
        switch (sex){
            case 1:
                System.out.println("男孩的特徵");
                break;
            case 2:
                System.out.println("女孩的特徵");
                break;
            default:
                System.out.println("引數錯誤");
        }
    }
}

以上程式碼,我們就很清楚引數傳入的是一個男孩,程式碼可讀性變好了。但是我們仍然能夠傳其他的int型別值。

為了限制該方法傳值的問題,於是我們引入了列舉,如下方法三:

方法三

使用列舉來實現該功能

package org.example;

enum StudentB{
    BOY,GIRL
}

public class Example3 {
    public static void main(String[] args) {
        choseStudent(StudentB.BOY);
    }
    public static void choseStudent(StudentB sex){
        switch (sex){
            case BOY:
                System.out.println("男孩的特徵");
                break;
            case GIRL:
                System.out.println("女孩的特徵");
                break;
            default:
                System.out.println("引數錯誤");
        }
    }
}

這樣不僅提高了程式碼的可讀性,也限制了呼叫者對該方法的傳值。

列舉的底層原理

我們將方法二中的類宣告為final 防止繼承,同事將構造方法宣告為private以防止外部例項化。這樣我們就可以保證,再程式內Student就只能有我們定義好的常量。如下:

package org.example.enumX;

final class StudentD{
    public static final StudentD BOY = new StudentD();
    public static final StudentD GIRL =  new StudentD();
    private StudentD(){}
}

透過上面的程式碼,我們也能限制呼叫者傳遞的內容。以上程式碼就類似為列舉的原理。

我們將方法三中的StudentB 列舉類的class檔案進行反編譯,可以看到如下程式碼:

PS D:\project\IDEAjava\testPro\demos\target\classes\org\example> javap .\StudentB.class
Compiled from "Example3.java"
final class org.example.StudentB extends java.lang.Enum<org.example.StudentB> {
  public static final org.example.StudentB BOY;
  public static final org.example.StudentB GIRL;
  public static org.example.StudentB[] values();
  public static org.example.StudentB valueOf(java.lang.String);
  static {};
}

相關文章