1. 程式人生 > 其它 >Enum(列舉類)

Enum(列舉類)

Enum(列舉類)

什麼情況下使用列舉類?

 有的時候一個類的物件是有限且固定的,這種情況下我們使用列舉類就比較方便?

為什麼不用靜態常量來替代列舉類呢?

public static final int SEASON_SPRING = 1;
public static final int SEASON_SUMMER = 2;
public static final int SEASON_FALL = 3;
public static final int SEASON_WINTER = 4;

  列舉類更加直觀,型別安全。使用常量會有以下幾個缺陷:

  1. 型別不安全。若一個方法中要求傳入季節這個引數,用常量的話,形參就是int型別,開發者傳入任意型別的int型別值就行,但是如果是列舉型別的話,就只能傳入列舉類中包含的物件。

  2. 沒有名稱空間。開發者要在命名的時候以SEASON_開頭,這樣另外一個開發者再看這段程式碼的時候,才知道這四個常量分別代表季節。

列舉類入門

  • 簡單的列舉類

    package enumcase;
    
    public enum SeasonEnum {
        SPRING,SUMMER,FALL,WINTER;
    }
    
    1. enum和class、interface的地位一樣
    2. 使用enum定義的列舉類預設繼承了java.lang.Enum,而不是繼承Object類。列舉類可以實現一個或多個介面。
    3. 列舉類的所有例項都必須放在第一行展示,不需使用new 關鍵字,不需顯式呼叫構造器。自動新增public static final修飾。
    4. 使用enum定義、非抽象的列舉類預設使用final修飾,不可以被繼承。
    5. 列舉類的構造器只能是私有的。

列舉類介紹

  • 列舉類內也可以定義屬性和方法,可是是靜態的和非靜態的。

    package enumcase;
    
    public enum SeasonEnum {
        SPRING("春天"),SUMMER("夏天"),FALL("秋天"),WINTER("冬天");
        
        private final String name;
        
        private SeasonEnum(String name)
        {
            this.name = name;
        }
    
        public String getName() {
            return name;
        }
    }
    
    • 實際上在第一行寫列舉類例項的時候,預設是呼叫了構造器的,所以此處需要傳入引數,因為沒有顯式申明無參構造器,只能呼叫有引數的構造器。
    • 構造器需定義成私有的,這樣就不能在別處申明此類的物件了。列舉類通常應該設計成不可變類,它的Field不應該被改變,這樣會更安全,而且程式碼更加簡潔。所以我們將Field用private final修飾。

列舉類實現介面

  • 列舉類可以實現一個或多個介面。與普通類一樣,實現介面的時候需要實現介面中定義的所有方法,若沒有完全實現,那這個列舉類就是抽象的,只是不需顯式加上abstract修飾,系統化會預設加上。

    package enumcase;
    
    public enum Operation {
        PLUS{
    
            @Override
            public double eval(double x, double y) {
                return x + y;
            }
            
        },
        MINUS{
    
            @Override
            public double eval(double x, double y) {
                return x - y;
            }
            
        },
        TIMES{
    
            @Override
            public double eval(double x, double y) {
                return x * y;
            }
            
        },
        DIVIDE{
    
            @Override
            public double eval(double x, double y) {
                return x / y;
            }
            
        };
        
        /**
         * 抽象方法,由不同的列舉值提供不同的實現。
         * @param x
         * @param y
         * @return
         */
        public abstract double eval(double x, double y);
        
        public static void main(String[] args) {
            System.out.println(Operation.PLUS.eval(10, 2));
            System.out.println(Operation.MINUS.eval(10, 2));
            System.out.println(Operation.TIMES.eval(10, 2));
            System.out.println(Operation.DIVIDE.eval(10, 2));
        }
    }
    
    • Operation類實際上是抽象的,不可以建立列舉值,所以此處在申明列舉值的時候,都實現了抽象方法,這其實是匿名內部類的實現,花括號部分是一個類體。我們可以看下編譯以後的檔案。

    • 共生成了五個class檔案,這樣就證明了PLUS,MINUS,TIMES,DIVIDE是Operation的匿名內部類的例項。

switch語句裡的表示式可以是列舉值

  • Java5新增了enum關鍵字,同時擴充套件了switch。

    public class SeasonTest {
        public void judge(SeasonEnum s)
        {
            switch(s)
            {
            case SPRING:
                System.out.println("春天適合踏青。");
                break;
            case SUMMER:
                System.out.println("夏天要去游泳啦。");
                break;
            case FALL:
                System.out.println("秋天一定要去旅遊哦。");
                break;
            case WINTER:
                System.out.println("冬天要是下雪就好啦。");
                break;
            }
        }
        
        public static void main(String[] args) {
            SeasonEnum s = SeasonEnum.SPRING;
            SeasonTest test = new SeasonTest();
            test.judge(s);
        }
    }
    
  • case表示式中直接寫入列舉值,不需加入列舉類作為限定。