一文了解java列舉

加油酱發表於2024-05-29

1. 列舉的由來

當我們知道所有變數的可能性時,儘量使用列舉型別來定義,比如季節,春夏秋冬,一週(一二三四五六七),只讀不需要修改
有限的一個一個列舉出來的類叫做列舉類,列舉是一組常量的集合,列舉也是一個特殊的類,裡面包含了一組有限的特定物件

2. 自定義實現列舉

  1. 不需要提供set方法,因為列舉物件值不能被修改(這裡注意列舉一般只用於知道所有固定變數的值)
  2. 構造器私有化
  3. 列舉物件/屬性用" final static""修飾
  4. 根據不同的類,生成不同數量的列舉物件,而且列舉物件定義全部大寫

引用前例子

這裡已知季節的所有變數是固定的春夏秋冬,可以用列舉來寫

package EG.列舉的由來;

   //設定季節,春夏秋冬  
  
public class Test {  
    public static void main(String[] args) {  
        /*  
         * 秋autumn  
         * 冬winter  
         * */
        Season spring = new Season("春天","暖和");  
        Season summer = new Season("夏天","酷熱");  
        Season autumn = new Season("秋天", "涼爽至極");  
        Season winter = new Season("冬天", "冰冷刺骨");  
        System.out.println(spring);  
  
    }  
}
package EG.列舉的由來;  
  
/**  
 * @author 簡水君  
 */  
public class Season {  
   /** 季節的名稱*/  
    private  String name;  
   /** 季節的資訊*/  
    private  String desc;  
  
  
    //javaBean  
  
    public Season() {  
    }  
    public Season(String name, String desc) {  
        this.name = name;  
        this.desc = desc;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public String getDesc() {  
        return desc;  
    }  
  
    public void setDesc(String desc) {  
        this.desc = desc;  
    }  
  
    @Override  
    public String toString() {  
        return   name+"的特點: "+desc;  
    }  
}

引用後例子

package EG.列舉的由來.引用後;  
  
   //設定季節,春夏秋冬  
  
public class Test {  
    public static void main(String[] args) {  
  
        System.out.println(Season.SPRING);  
        System.out.println(Season.SUMMER);  
        System.out.println(Season.SPRING);  
        System.out.println(Season.WINTER);  
    }  
}

這裡模擬Season類繼承enum類稱為列舉類,其次是季節都是固定的值,不能再次建立也不能修改,將構造器私有化,把set方法刪除,建立靜態物件

package EG.列舉的由來.引用後;  
  
/**  
 * @author 簡水君  
 */  
public class Season {  
    /**  
     * 季節的名稱  
     */  
    private String name;  
    /**  
     * 季節的資訊  
     */  
    private String desc;  
  
    //javaBean  
  
    /** 這裡模擬Season類繼承enum類稱為列舉類 */  
  
	public final static Season SPRING = new Season("春天", "暖和");  
	public final static Season SUMMER = new Season("夏天", "酷熱");  
	public final static Season AUTUMN = new Season("秋天", "涼爽至極");  
	public final static Season WINTER = new Season("冬天", "冰冷刺骨");
  
    private Season(String name, String desc) {  
        this.name = name;  
        this.desc = desc;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public String getDesc() {  
        return desc;  
    }  
  
    @Override  
    public String toString() {  
        return name + "的特點: " + desc;  
    }  
}

3.列舉的使用

定義列舉用名詞enum ,第一行只能是常量(最終靜態/類的物件的縮寫),多個常量用逗號分隔,後面行隨意
格式:

  1. 無參時: 變數名1,變數名2,變數名3; 等價於 變數n()
  2. 有參時; 變數名1(實參),變數名2(實參),變數名3(實參);
package EG.b列舉的使用;  

/**  
* @author 簡水君  
*/  
 
 
//設定季節,春夏秋冬  
 
public class Test {  
   public static void main(String[] args) {  
 
       System.out.println(Season.SPRING);  
       System.out.println(Season.SUMMER);  
       System.out.println(Season.SPRING);  
       System.out.println(Season.WINTER);  
 
   }  
}  
 
enum Season {  
    //這裡季節都是固定的值把set方法刪除  
/* 這裡 SPRING("春天", "暖和")相當於 public final static Season SPRING = new Season("春天", "暖和");  假設有個無參常量 SPRING,也是等價於SPRING()的*/
   SPRING("春天", "暖和"),SUMMER("夏天", "酷熱"),AUTUMN("秋天", "涼爽至極"),WINTER("冬天", "冰冷刺骨");  
 
   //javaBean  
   /**  
    * 季節的名稱  
    */  
   private String name;  
   /**  
    * 季節的資訊  
    */  
   private String desc;  
   private Season(String name, String desc) {  
       this.name = name;  
       this.desc = desc;  
   }  
 
   public String getName() {  
       return name;  
   }  
 
   public String getDesc() {  
       return desc;  
   }  
 
   @Override  
   public String toString() {  
       return name + "的特點: " + desc;  
   }  
}

4.反編譯enum類

這裡 底層將該季節類Season為最終類,不能被繼承且繼承了Enum介面,有其方法values(),valueOf(),還有一個靜態程式碼塊

練習題

這裡BOY,GIRL都是建立了無參的常量物件,這裡輸出boy指的是Boy的物件(類載入時載入一次靜態最終常量),但這裡沒有重寫Enum的toString()方法,所以指的是其常量名字,兩個引用指向一個物件

5.列舉enum的方法

package EG.c列舉方法的使用;  
  
import java.util.Arrays;  
  
/**  
 * @author 簡水君  
 */  
public class Test {  
    public static void main(String[] args) {  
        Season sp = Season.SPRING;  
        // 1. toString()這裡返回的是列舉物件的名字 SPRING        System.out.println(sp);  
        // 2. name()這裡返回的也是列舉物件的名字 SPRING        System.out.println(sp.name());  
        // 3.返回的是列舉物件的索引位置 0 , 可以用於comparable比較  
        System.out.println(sp.ordinal());  
        // 4. values() 這裡返回的是一個列舉的所有常量的陣列  
        Season[] values = Season.values();  
        System.out.println(Arrays.toString(values));  
        // for( Season s :  values ){}  
  
        // 5. valueOf(" ")獲取包含字串的常量物件  
        Season sa = Season.valueOf("WINTER");  
        System.out.println(sa);  
  
        // 6.CompareTo: 比較兩個列舉常量,比較的是編號的差值,底層是兩者呼叫ordinal方法的差值,這可以算出兩個常量位置的差值  
        //春天和冬天的差值0-3  
        int i = Season.SPRING.compareTo(Season.WINTER);  
        System.out.println(i);  
  
    }  
}  
  
enum Season {  
    SPRING("春天", "暖和"), SUMMER("夏天", "酷熱"), AUTUMN("秋天", "涼爽至極"), WINTER("冬天", "冰冷刺骨");  
    private String name;  
    private String desc;  
  
    private Season() {  
    }  
    private Season(String name, String desc) {  
        this.name = name;  
        this.desc = desc;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    public String getDesc() {  
        return desc;  
    }  
  
}

例子

package EG.d練習題;  
  
import java.util.Arrays;  
import java.util.PropertyResourceBundle;  
  
/**  
 * @author 簡水君  
 */  
public class Test {  
    public static void main(String[] args) {  
    //獲取所有的常量陣列,遍歷  
        Week[] values = Week.values();  
        System.out.println("所有星期資訊如下: ");  
        for (Week value : values) {  
            System.out.print(value+" ");  
        }  
    }  
}  
  
/**  
因為我們知道一週所有變數固定的值,所以用列舉來寫,而且各個變數不給改變,  
 而且定義的Week的是最終類,不給繼承,但可以建立物件  
*/  
enum Week{  
    MONDAY("週一"),TUESDAY("週二"),WEDNESDAY("週三"),THURSDAY("週四"),FRIDAY("週五"),SATURDAY("週六"),SUNDAY("週末");  
  
    private  String name;  
  
  
   private Week() {  
    }  
    private Week(String name) {  
        this.name = name;  
    }  
  
    public String getName() {  
        return name;  
    }  
  
    @Override  
    public String toString() {  
        return name;  
    }  
}

6.列舉實現介面

  1. 使用enum關鍵字後,就不能再繼承其他類了,但enum定義的類底層會繼承Enum介面,這算是java的單繼承機制了
  2. 列舉類和普通類一樣,可以實現介面,如下形式 enum 類名 implements 介面1,介面2{} ,多幾個義父
package EG.e列舉實現介面;  
  
public class Test {  
    public static void main(String[] args) {  
  
    //    呼叫列舉的方法  
        Music.GUANGHUISUIYUE.play();  
    }  
}  
  
enum  Music implements Play{  
    //定義一個音樂物件  
    GUANGHUISUIYUE;  
  
    @Override  
    public void play() {  
        //列印常量的名稱  
        System.out.println("正在播放🎵: "+Music.GUANGHUISUIYUE.name());  
    }  
}  
  
interface  Play{  
    void play();  
}

7.列舉的特點

  1. 列舉的第一行只能羅列一些名稱,這些名稱都是常量,並且每個常量記住的都是列舉類的一個物件
  2. 列舉都是final修飾的最終類,不能被繼承的,且不能建立物件
  3. 列舉類中,第二行開始,可以定義類的其他各種成員
  4. 列舉類都是繼承的java.lang.Enum 的方法
  5. 列舉變數 = spring("春天","暖和") ,Season spring = new Season("春天","暖和");

8.為什麼說列舉常量是一個單例設計模式

因為 列舉常量是最終的final修飾的 ,不可改變的,只能建立一次 .透過使用列舉來定義常量集合,可以確保常量的唯一性和不可變性。
由於列舉常量在編譯時就被建立並且在執行時只有一個例項,所以可以避免多執行緒併發訪問下導致的執行緒安全問題。

9.列舉作為限制傳值

這裡對於provideInfo(),只能傳BOY/Girl

相關文章