最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?枚舉的定義、使用詳解

 更新時間:2025年12月31日 11:18:03   作者:楠枬  
本文介紹了Java中的枚舉(enum)概念,包括枚舉的定義、使用和常用方法,枚舉是一種特殊的類,用于定義一組常量,使得代碼更具有可讀性和可維護(hù)性,枚舉類默認(rèn)繼承自java.lang.Enum類,且不能被繼承,本文給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

枚舉是什么

枚舉(enum):是一種特殊的類,用于定義一組常量,將其組織起來。枚舉使得代碼更具有可讀性和可維護(hù)性,特別是在處理固定集合的值時,如:星期、月份、狀態(tài)碼等

在 Java 中,使用關(guān)鍵字 enum 來定義枚舉類:

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
}

其中,定義的枚舉項就是該類的實例,且必須在第一行,最后一個枚舉項后的分號; 可以省略,但是若枚舉類有其他內(nèi)容,則分號不能省略(最好不要省略) 

當(dāng)類初始化時,這些枚舉項就會被實例化

枚舉類使用 enum 定義后,默認(rèn)繼承 java.lang.Enum 類,也就是說,我們自己寫的枚舉類,就算沒有顯示的繼承 Enum,但是其默認(rèn)繼承了這個類

此外,枚舉在 Java 中不能被繼承,自定義的枚舉類隱式繼承自 java.lang.Enum 類,且不能再繼承其他類,這樣的設(shè)計確保了枚舉類的簡單性和一致性。如果枚舉可以繼承其他類,將會導(dǎo)致復(fù)雜的繼承關(guān)系,并且影響Java的類型系統(tǒng)

常用方法

方法描述
values()以數(shù)組的形式返回枚舉類型的所有成員

ordinal()

獲取枚舉成員的索引位置
valueOf()將普通字符串轉(zhuǎn)換為枚舉實例

compareTo(E o)

比較兩個枚舉成員在定義時的順序

 我們通過一個示例,來學(xué)習(xí)和使用這些方法:

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
    public static void main(String[] args) {
        // 獲取所有枚舉成員
        Day[] days = Day.values();
        // 遍歷
        for (int i = 0; i < days.length; i++) {
            // 獲取枚舉成員以及索引位置
            System.out.println(days[i] + " " + days[i].ordinal());
        }
        // 將普通字符串轉(zhuǎn)換為枚舉實例
        System.out.println(Day.valueOf("THURSDAY"));
        // 獲取枚舉實例 SUNDAY 和 SATURDAY
        Day sunday = Day.SUNDAY;
        Day saturday = Day.SATURDAY;
        // 比較定義時的順序
        System.out.println(sunday.compareTo(saturday));
    }
}

運行結(jié)果:

在使用 valueOf() 方法進(jìn)行轉(zhuǎn)換時,傳遞的名稱必須與枚舉常量的名字完全匹配(包括大小寫),若不匹配,就會拋出 IllegalArgumentException 異常:

 當(dāng)我們查看 java.lang.Enum 時:

可以看到,valueOf() 方法包含了兩個類型的參數(shù):Class<T> enumClass  和  String name

其中

Class<T> enumType 是一個 Class 對象,表示要查找的枚舉類型

String name: 是一個字符串,表示要查找的枚舉常量的名稱。名稱必須與枚舉常量的名字完全匹配(包括大小寫)

 但是在使用時,我們只傳遞了一個參數(shù) name,也能夠進(jìn)行轉(zhuǎn)換,這是為什么呢?

這是因為,在 Java 中,valueOf 方法實際上是自動生成的,屬于每個枚舉類型的特性。雖然它的原始定義需要兩個參數(shù)(類類型和名稱),但是每個枚舉類型都會自動提供一個與自身類型相關(guān)聯(lián)的 valueOf 方法,只需傳遞一個字符串參數(shù)

因此,當(dāng)我們調(diào)用 Day.valueOf("THURSDAY") 時,Java會自動處理這個調(diào)用,實際調(diào)用的是包含類名的 valueOf 方法,而不是原始的靜態(tài)方法定義

再觀察 java.lang.Enum:

我們會發(fā)現(xiàn),其中并不存在 values() 這個方法,而當(dāng)我們點擊 values() 方法時,則會跳轉(zhuǎn)到本類上

那么,values() 方法是從哪來的呢?

values() 方法是枚舉類自動提供的一個靜態(tài)方法,允許我們獲取一個包含所有枚舉常量的數(shù)組,這個方法是由Java編譯器自動生成的,在編譯時每個枚舉類型都會自動生成一個 values() 方法,因此不需要我們顯式定義它

我們將枚舉類進(jìn)行反編譯:

(1)打開 cmd,切換到 Day.java 文件所在目錄

(2)編譯 .java 文件(javac Day.java)

(3)將 .class 文件進(jìn)行反編譯(javap -c Day.class > day.txt)

打開 day.txt,可以看到:

編譯器自動為我們生成了 values 和 valueOf 方法

構(gòu)造方法

當(dāng)我們創(chuàng)建構(gòu)造方法時:

 不能使用 public 來修飾構(gòu)造方法,為什么呢?

這是因為,在 Java 中,枚舉類的構(gòu)造方法都是私有的(不加任何修飾符時,默認(rèn)是 private),無法在枚舉類外部調(diào)用,這也就防止了在枚舉類外部創(chuàng)建新的枚舉常量

在定義枚舉常量時,構(gòu)造方法會被隱式調(diào)用:

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY;
    Day() {
        System.out.println("構(gòu)造方法");
    }
    public static void main(String[] args) {
        System.out.println("------------------");
    }
}

運行結(jié)果: 

 當(dāng)我們定義帶有參數(shù)的構(gòu)造方法時,在創(chuàng)建枚舉項時,也要為其提供對應(yīng)參數(shù):

public enum Day {
    SUNDAY("周天", 7),
    MONDAY("周一", 1),
    TUESDAY("周二", 2),
    WEDNESDAY("周三", 3),
    THURSDAY("周四", 4),
    FRIDAY("周五", 5),
    SATURDAY("周六", 6);
    private String name;
    private int key;
    Day(String name, int key) {
        this.name = name;
        this.key = key;
    }
}

枚舉的優(yōu)缺點

優(yōu)點:

(1)枚舉常量確保了只能使用定義的常量,避免了使用整型常量時可能帶來的錯誤

(2)使用枚舉可以使代碼更易讀,表達(dá)清晰

(3)枚舉定義了一組固定的常量,適合表示有限的狀態(tài)或選項,便于管理和維護(hù)

(4)枚舉可以擁有字段、方法和構(gòu)造方法,能夠封裝與常量相關(guān)的行為和屬性

(5)Java的枚舉類自帶一些方法,如 values()、valueOf() 等

(6)可以用于 switch 語句

缺點:

(1)枚舉的集合是固定的,無法在運行時添加或刪除常量。如果需要動態(tài)的集合,枚舉可能不適用

(2)枚舉不能繼承,無法擴展

(3)每個枚舉常量都是一個對象,可能會增加內(nèi)存使用,特別是當(dāng)枚舉常量數(shù)量較多時

枚舉和反射

 Java 反射 中,我們學(xué)習(xí)了反射,通過反射,我們可以拿到類的私有構(gòu)造方法,從而創(chuàng)建實例對象

那么,枚舉是否可以通過反射,拿到實例對象呢?

public enum Day {
    SUNDAY("周天", 7),
    MONDAY("周一", 1),
    TUESDAY("周二", 2),
    WEDNESDAY("周三", 3),
    THURSDAY("周四", 4),
    FRIDAY("周五", 5),
    SATURDAY("周六", 6);
    private String name;
    private int key;

    Day(String name, int key) {
        this.name = name;
        this.key = key;
    }
}
public class Test {
    public static void main(String[] args) {
        Class<?> classDay = null;
        try {
            classDay = Class.forName("Day");
            Constructor<?> constructor = classDay.getDeclaredConstructor(String.class, int.class);
            constructor.setAccessible(true);
            Day day = (Day) constructor.newInstance("sunday", 0);
            System.out.println(day.ordinal());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

運行結(jié)果:

此時程序拋出了 NoSuchMethodException 異常,也就是沒有對應(yīng)的構(gòu)造方法

但是提供的枚舉的構(gòu)造方法就是帶有兩個參數(shù),分別為 String 和 int:

那么,問題出在哪里呢?

自定義的枚舉類默認(rèn)繼承自 java.lang.Enum

因此,自定義的枚舉類繼承了父類除構(gòu)造方法外的所有東西,且子類需要幫助父類進(jìn)行構(gòu)造,

但我們實現(xiàn)的類中,并沒有幫助父類進(jìn)行構(gòu)造

因此,我們需要在枚舉類中幫助父類進(jìn)行構(gòu)造,而父類中的構(gòu)造方法為:

那么,如何實現(xiàn)呢?通過 super 方法嗎?

但是,當(dāng)我們在構(gòu)造方法中調(diào)用 super 時:

枚舉構(gòu)造方法中不能使用 super

 由于枚舉比較特殊,在構(gòu)造方法中,除了我們自定義了兩個參數(shù),它還默認(rèn)添加了父類的兩個參數(shù)

也就是說,構(gòu)造函數(shù)中一共有四個參數(shù):String int String int

其中,前兩個參數(shù)是父類參數(shù),后兩個參數(shù)是子類參數(shù)

public class Test {
    public static void main(String[] args) {
        Class<?> classDay = null;
        try {
            classDay = Class.forName("enumDemo.Day");
            Constructor<?> constructor = classDay.getDeclaredConstructor(String.class, int.class, String.class, int.class);
            constructor.setAccessible(true);
            Day day = (Day) constructor.newInstance("父類參數(shù)", 0, "子類參數(shù)", 0);
            System.out.println(day.ordinal());
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

再次運行:

此時拋出了 IllegalArgumentException 異常,不能通過反射創(chuàng)建枚舉對象

枚舉保證了每個枚舉常量只有一個實例,這種唯一性在枚舉類型被定義時就已經(jīng)確定,不允許外部創(chuàng)建新的實例,枚舉類型的設(shè)計使得它們的實例在類加載時被唯一地定義,從而避免了通過反射創(chuàng)建新的枚舉實例的可能性,確保了枚舉的強類型安全性和唯一性

實現(xiàn)單例模式

在 單例模式:餓漢模式、懶漢模式_單例模式懶漢和餓漢-CSDN博客 中我們實現(xiàn)了單例模式,單例模式能夠確保一個類只有一個實例

但普通類可以通過反射機制打破,因此,我們可以使用枚舉來實現(xiàn)單例模式

public enum Singleton {
    INSTANCE;
    public Singleton getInstance() {
        return INSTANCE;
    }
}

到此這篇關(guān)于Java 枚舉的定義、使用詳解的文章就介紹到這了,更多相關(guān)Java 枚舉內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

浦东新区| 砀山县| 潍坊市| 韶山市| 马龙县| 同德县| 攀枝花市| 田阳县| 简阳市| 湖南省| 沁源县| 凤城市| 鹿泉市| 宜川县| 鄱阳县| 景宁| 金寨县| 白银市| 西乡县| 资源县| 武山县| 松江区| 田阳县| 芷江| 平昌县| 石阡县| 历史| 永兴县| 鲁甸县| 新化县| 江津市| 武鸣县| 望奎县| 游戏| 嘉禾县| 祥云县| 东乌珠穆沁旗| 通许县| 长子县| 闽清县| 洪雅县|