Java筆記:枚舉類


1.一個類的實例是有限且固定的,這個類稱為枚舉類。比如季節類,只有四個對象(春、夏、秋、冬)

2.手動實現一個枚舉類
(1)通過private將構造器隱藏起來
(2)把這個類的所有可能實例都使用private static final修飾的類變量來保存。
(3)如果有必要,可以提供一些靜態方法。

package cn.it.lsl;

public class Season {
    private final String name;
    private final String desc;
    private Season(String name, String desc){
        this.name = name;
        this.desc = desc;
    }
    public static final Season SPRING = new Season("春天","踏青");
    public static final Season SUMMER = new Season("夏天","夏日炎炎");
    public static final Season FAIL = new Season("秋天","秋高氣爽");
    public static final Season WINTER = new Season("冬天","白雪皚皚");
    
    public String getName(){
        return this.name;
    }
    public String getDesc(){
        return this.desc;
    }
}
package cn.it.lsl;

public class SeasonTest {
    public SeasonTest(Season s){
        System.out.println(s.getName() + "," + s.getDesc());
    }
    public static void main(String[] args) {
        new SeasonTest(Season.FAIL);
    }
}

Season類是一個不可變類。Season類中包含了4個static final常量的Field,這4個常量Field就代表了該類所能創建的對象。當程序需要調用Season對象時,就可以通過Season.SPRING的方式來取得Season對象。

這里順便復習一下不可變類
不可變類:創建該類的實例后,該實例的Field是不可改變的。
如果要創建自定義的不可變類,需遵循如下規則:
(1)使用private和final修飾符來修飾該類的Field。
(2)提供帶參數的構造函數,用於根據傳入參數來初始化類里的Field。
(3)僅為該類的Field提供getter方法,不要為該類的Field提供setter方法。
(4)如果有必要,重寫Object類的hashCode和equals方法。

3.枚舉類
(1)使用enum關鍵字定義枚舉類。枚舉類一樣可以有自己的Field、方法,可以實現一個或多個接口,也可以有自己的構造器。
(2)使用eunm定義的枚舉類默認繼承了java.lang.Enum類,而不是繼承Object類。
(3)使用enum定義、非抽象的枚舉類默認會使用final修飾,因此枚舉類不能派送子類。(並不是所有的枚舉類都使用final修飾,如抽象枚舉類)
(4)枚舉類所有實例必須在枚舉類的第一行顯示列出,否則這個枚舉類永遠不能產生實例。
(5)所有枚舉類都提供一個values方法,該方法可以方便地遍歷所有枚舉值。

package cn.lsl;

public enum SeasonEnum {
    SPRING,SUMMER,FALL,WINTER;
}
package cn.lsl;

public class EnumTest {
    
    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) {
        //列出所有枚舉類的實例
        for(SeasonEnum s : SeasonEnum.values()){
            System.out.println(s);
        }
        
        new EnumTest().judge(SeasonEnum.FALL);
    }
}

4.枚舉類的Field、方法

枚舉類可以定義自己的Field和方法。

package cn.lsl;

public enum Gender {
    MALE,FEMALE;
    public String name;
}
package cn.lsl;

public class GenderTest {
    public static void main(String[] args) {
        //通過Enum的valueOf方法來獲取指定枚舉類的枚舉值
        Gender g = Enum.valueOf(Gender.class, "FEMALE");
        g.name = "女";
        System.out.println(g + "," + g.name);
    }
}

在上面程序中產生Gender對象的方式與普通類不同,而是采用通過Enum的valueOf方法來獲取指定枚舉類的枚舉值,枚舉類的實例只能是枚舉值,而不是隨意通過new來創建的。

其實上面程序中,沒有實現java的良好封裝,因為name的訪問權限是public,這樣就會出現隨意對name賦值的情況,應該通過方法來控制對name的訪問。

改造上面的程序

package cn.lsl;

public enum Gender {
    MALE,FEMALE;
    public String name;
    public void setName(String name){
        switch(this){
            case MALE:
                if(name.equals("男")){
                    this.name = name;
                }else{
                    System.out.println("參數錯誤");
                    return;
                }
                break;
            case FEMALE:
                if(name.equals("女")){
                    this.name = name;
                }else{
                    System.out.println("參數錯誤");
                    return;
                }
                break;
        }
    }
    public String getName(){
        return this.name;
    }
}
package cn.lsl;

public class GenderTest {
    public static void main(String[] args) {
        //通過Enum的valueOf方法來獲取指定枚舉類的枚舉值
        Gender g = Enum.valueOf(Gender.class, "FEMALE");
        g.setName("女");
        System.out.println(g + "," + g.getName());
        g.setName("男");
        System.out.println(g + "," + g.getName());
    }
}

定義枚舉類,以上的做法還是做的不夠好,枚舉類通常應該設計不可變類。其Field值不應該允許改變,這樣會更安全。

所以枚舉類的Field都應該使用private final修飾。

package cn.lsl;

public enum Gender {
    MALE("男"),FEMALE("女");
    private final String name;
    private Gender(String name){
        this.name = name;
    }
    public String getName(){
        return this.name;
    }
}

5.實現接口的枚舉類

枚舉類可以實現一個或多個接口。

package cn.it.lsl;

public interface GenderDesc {
    void info();
}
package cn.it.lsl;

public enum Gender implements GenderDesc{
    MALE("男"),FEMALE("女");
    private final String name;
    private Gender(String name){
        this.name = name;
    }
    
    public String getName(){
        return this.name;
    }

    @Override
    public void info() {
        // TODO Auto-generated method stub
        System.out.println("枚舉類實現接口");
    }

}

以上在枚舉類里面實現接口的方法時,每個枚舉值在調用該方法的時候都會有相同的行為(即方法體相同)。
如果需要每個枚舉值在調用該方法時表現出不同的行為方式,應該讓每個枚舉值分別實現該方法。

package cn.it.lsl;

public enum Gender implements GenderDesc{
    MALE("男"){
        public void info() {
            // TODO Auto-generated method stub
            System.out.println("枚舉類實現接口,男");
        }
    },
    FEMALE("女"){
        public void info() {
            // TODO Auto-generated method stub
            System.out.println("枚舉類實現接口,女");
        }
    };
    private final String name;
    private Gender(String name){
        this.name = name;
    }
    
    public String getName(){
        return this.name;
    }
}

6.包含抽象方法的枚舉類

在枚舉類中定義抽象方法的時候不能使用abstract關鍵字將枚舉類定義成抽象類(因為系統會自動為它添加abstract關鍵字),因為枚舉類需要顯示創建枚舉值,而不是作為父類,所以定義每個枚舉值時必須為抽象方法提供實現。

以下一個程序在枚舉類中定義了一個抽象方法,這個抽象方法由不同的枚舉值提供不同的實現

package cn.it.lsl;

public enum Operation {
    PLUS{
        @Override
        public double eval(double x, double y) {
            // TODO Auto-generated method stub
            return x + y;
        }
    },
    MINUS{
        @Override
        public double eval(double x, double y) {
            // TODO Auto-generated method stub
            return x - y;
        }
    },
    TIMES{
        @Override
        public double eval(double x, double y) {
            // TODO Auto-generated method stub
            return x * y;
        }
    },
    DIVIDE{
        @Override
        public double eval(double x, double y) {
            // TODO Auto-generated method stub
            return x / y;
        }
    };
    public abstract double eval(double x, double y);
    
    
    public static void main(String[] args) {
        System.out.println(Operation.PLUS.eval(2, 3));
        System.out.println(Operation.MINUS.eval(2, 3));
        System.out.println(Operation.TIMES.eval(2, 3));
        System.out.println(Operation.DIVIDE.eval(2, 3));
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM