1. 列舉的由來
當我們知道所有變數的可能性時,儘量使用列舉型別來定義,比如季節,春夏秋冬,一週(一二三四五六七),只讀不需要修改
有限的一個一個列舉出來的類叫做列舉類,列舉是一組常量的集合,列舉也是一個特殊的類,裡面包含了一組有限的特定物件
2. 自定義實現列舉
- 不需要提供set方法,因為列舉物件值不能被修改(這裡注意列舉一般只用於知道所有固定變數的值)
- 構造器私有化
- 列舉物件/屬性用" final static""修飾
- 根據不同的類,生成不同數量的列舉物件,而且列舉物件定義全部大寫
引用前例子
這裡已知季節的所有變數是固定的春夏秋冬,可以用列舉來寫
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,變數名2,變數名3;
等價於變數n()
- 有參時;
變數名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.列舉實現介面
- 使用enum關鍵字後,就不能再繼承其他類了,但enum定義的類底層會繼承Enum介面,這算是java的單繼承機制了
- 列舉類和普通類一樣,可以實現介面,如下形式
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.列舉的特點
- 列舉的第一行只能羅列一些名稱,這些名稱都是常量,並且每個常量記住的都是列舉類的一個物件
- 列舉都是final修飾的最終類,不能被繼承的,且不能建立物件
- 列舉類中,第二行開始,可以定義類的其他各種成員
- 列舉類都是繼承的java.lang.Enum 的方法
- 列舉變數 = spring("春天","暖和") ,Season spring = new Season("春天","暖和");
8.為什麼說列舉常量是一個單例設計模式
因為 列舉常量是最終的final修飾的 ,不可改變的,只能建立一次 .透過使用列舉來定義常量集合,可以確保常量的唯一性和不可變性。
由於列舉常量在編譯時就被建立並且在執行時只有一個例項,所以可以避免多執行緒併發訪問下導致的執行緒安全問題。
9.列舉作為限制傳值
這裡對於provideInfo(),只能傳BOY/Girl