Java魔法堂:枚举类型详解
一、前言
? Java的枚舉類型相對C#來說具有更靈活可配置性,Java的枚舉類型可以攜帶更多的信息。
? 本文將對枚舉類型進行較為詳細的敘述,以便日后查閱。
?
二、最簡單的用法——常量
? 枚舉值的name()會返回枚舉值的字面量,而ordinal()為返回枚舉值的索引,而索引是以枚舉值定義時的位置來確定,并在編譯時設置的。下面我們來看看到底編譯器為我們做了什么?
final class MyColor extends java.lang.Enum<MyCorlor>{public static final MyColor RED;flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUMpublic static final MyColor BLUE;flags: ACC_PUBLIC, ACC_STATIC, ACC_FINAL, ACC_ENUMpublic static MyColor[] values();flags: ACC_PUBLIC, ACC_STATICCode:stack=1, locals=0, args_size=00: getstatic #1 // Field $VALUES:[LMyColor;3: invokevirtual #2 // Method "[LMyColor;".clone:()Ljava/lang/Object;6: checkcast #3 // class "[LMyColor;"9: areturn LineNumberTable:line 1: 0public static MyClass valueOf(java.lang.String);flags: ACC_PUBLIC, ACC_STATICCode:stack=2, locals=1, args_size=10: ldc_w #4 // class MyColor3: aload_0 4: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;7: checkcast #4 // class MyColor10: areturn LineNumberTable:line 1: 0static {};flags: ACC_STATICCode:stack=4, locals=0, args_size=00: new #4 // class MyColor3: dup 4: ldc #7 // String RED6: iconst_0 7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V10: putstatic #9 // Field RED:LMyColor;13: new #4 // class MyColor16: dup 17: ldc #10 // String BLUE19: iconst_1 20: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V23: putstatic #11 // Field BLUE:LMyColor;26: iconst_2 27: anewarray #4 // class MyColor30: dup 31: iconst_0 32: getstatic #9 // Field RED:LMyColor;35: aastore 36: dup 37: iconst_1 38: getstatic #11 // Field BLUE:LMyColor;41: aastore 42: putstatic #1 // Field $VALUES:[LMyColor;45: return LineNumberTable:line 2: 0line 1: 26 }
?可以看到編譯器將enum MyColor編譯為一個繼承Enum<MyColor>并且帶修飾符final的MyColor類。
?而枚舉值RED和BLUE則被編譯為MyColor的類常量,并且在類加載的初始化階段實例化。MyColor默認的構造函數會調用父類 Enum<MyColor>的構造函數Enum<E>(String name, int ordinal)來設置私有字段name和ordinal的值。其中iconst_0和iconst_1分別表示將0和1壓 棧,invokespecial #8則是調用構造函數Enum<E>(String name, int ordinal)。
26: iconst_2 27: anewarray #4 // class MyColor30: dup 31: iconst_0 32: getstatic #9 // Field RED:LMyColor;35: aastore 36: dup 37: iconst_1 38: getstatic #11 // Field BLUE:LMyColor;41: aastore 42: putstatic #1 // Field $VALUES:[LMyColor;
? 小結:
? ? ?1. 定義枚舉類型本質上就是在定義帶final修飾符的Enum<E>的子類;
? ? ?2. 枚舉值本質為第1點所定義的類的類常量;
? ? ?3. 枚舉值的ordinal值由其定義時的排序決定,并且在編譯時已經被設置好了。
?
三、枚舉類型的抽象父類Enum<E> ?
? 其實我們大多數情況下都是調用父類Enum<E>的方法來操作自定義的枚舉值,下面一起看看父類Enum<E>吧!
? 1. 它為抽象類且繼承了Comparable<E>和Serializable兩個類。
? 2. 內含私有字段name和ordinal和對應的公有get方法name()和ordinal()。
? 3. 重寫了equals方法,通過==比較兩個枚舉值的內存地址來判斷兩者是否相同。
? 4. 實現compareTo方法,通過比較兩個枚舉值的ordinal值來做判斷。
? 5.?getDeclaringClass方法,用于返回枚舉的Class對象。
?
四、攜帶更多信息——自定義構造函數
? 由于枚舉最終被編譯為類,因此我們通過自定義構造函數、自定義字段和方法來讓枚舉值攜帶更多信息
? 注意:
? ? 1. 自定義的構造函數必須是私有的;
? ? 2. 構造函數內不能顯式調用父類的構造函數;
? ? 3. RED、BLUE的ordinal值依然是0和1,那么值依然是RED和BLUE。
?上述3點規定和結果的原因是編譯器會對我們的自定義構造函數進行加工變為
? 可以看到枚舉值RED和BLUE同一個方法具有不同的行為。其實這是通過匿名內部類的方式實現的,BLUE的類型為MyColor$1 extends MyColor,而RED的類型為MyColor。
?
六、使用接口組織枚舉
七、總結
? 若有紕漏請大家指正,謝謝。
總結
以上是生活随笔為你收集整理的Java魔法堂:枚举类型详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Nagios 监控系列学习 —— 简
- 下一篇: ngnix服务器搭建