日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java源码分析--Enum

發布時間:2025/3/21 java 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java源码分析--Enum 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Enum類是java.lang包中一個類,他是Java語言中所有枚舉類型的公共基類

定義

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable
  • 1

抽象類

  • 首先,抽象類不能被實例化,所以我們在java程序中不能使用new關鍵字來聲明一個Enum,如果想要定義可以使用這樣的語法:
enum enumName{value1,value2method1(){}method2(){} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 其次,看到抽象類,第一印象是肯定有類繼承他。至少我們應該是可以繼承他的,所以:
/*** @author hollis*/ public class testEnum extends Enum{ } public class testEnum extends Enum<Enum<E>>{ } public class testEnum<E> extends Enum<Enum<E>>{ }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 嘗試了以上三種方式之后,得出以下結論:Enum類無法被繼承

  • 為什么一個抽象類不讓繼承?enum定義的枚舉是怎么來的?難道不是對Enum的一種繼承嗎?帶著這些疑問我們來反編譯以下代碼:

enum Color {RED, BLUE, GREEN}
  • 1
  • 編譯器將會把他轉成如下內容:
/*** @author hollis*/ public final class Color extends Enum<Color> {public static final Color[] values() { return (Color[])$VALUES.clone(); }public static Color valueOf(String name) { ... }private Color(String s, int i) { super(s, i); }public static final Color RED;public static final Color BLUE;public static final Color GREEN;private static final Color $VALUES[];static {RED = new Color("RED", 0);BLUE = new Color("BLUE", 1);GREEN = new Color("GREEN", 2);$VALUES = (new Color[] { RED, BLUE, GREEN });} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 短短的一行代碼,被編譯器處理過之后竟然變得這么多,看來,enmu關鍵字是java提供給我們的一個語法糖啊。。。從反編譯之后的代碼中,我們發現,編譯器不讓我們繼承Enum,但是當我們使用enum關鍵字定義一個枚舉的時候,他會幫我們在編譯后默認繼承java.lang.Enum類,而不像其他的類一樣默認繼承Object類。且采用enum聲明后,該類會被編譯器加上final聲明,故該類是無法繼承的。 PS:由于JVM類初始化是線程安全的,所以可以采用枚舉類實現一個線程安全的單例模式

實現Comparable和Serializable接口

  • Enum實現了Serializable接口,可以序列化。 Enum實現了Comparable接口,可以進行比較,默認情況下,只有同類型的enum才進行比較(原因見后文),要實現不同類型的enum之間的比較,只能復寫compareTo方法

泛型 “<”E extends Enum”<”E>>

  • 怎么理解 “<”E extends Enum”<”E>>

首先,這樣寫只是為了讓Java的API更有彈性,他主要是限定形態參數實例化的對象,故要求只能是Enum,這樣才能對 compareTo 之類的方法所傳入的參數進行形態檢查。所以,我們完全可以不必去關心他為什么這么設計

  • 首先我們先來“翻譯”一下這個Enum

/*** @author hollis*/ enum Color{RED,GREEN,YELLOW } enum Season{SPRING,SUMMER,WINTER } public class EnumTest{public static void main(String[] args) {System.out.println(Color.RED.ordinal());System.out.println(Season.SPRING.ordinal());} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 代碼中兩處輸出內容都是 0 ,因為枚舉類型的默認的序號都是從零開始的

  • 要理解這個問題,首先我們來看一個Enum類中的方法(暫時忽略其他成員變量和方法):

/*** @author hollis*/ public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {private final int ordinal;public final int compareTo(E o) {Enum other = (Enum)o;Enum self = this;if (self.getClass() != other.getClass() && // optimizationself.getDeclaringClass() != other.getDeclaringClass())throw new ClassCastException();return self.ordinal - other.ordinal;} }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 首先我們認為Enum的定義中沒有使用Enum
public final int compareTo(Object o)
  • 1
  • 當我們調用compareTo方法的時候依然傳入兩個枚舉類型,在compareTo方法的實現中,比較兩個枚舉的過程是先將參數轉化成Enum類型,然后再比較他們的序號是否相等。那么我們這樣比較:
Color.RED.compareTo(Color.RED); Color.RED.compareTo(Season.SPRING);
  • 1
  • 2
  • 如果在compareTo方法中不做任何處理的話,那么以上這段代碼返回內容將都是true(因為Season.SPRING的序號和Color.RED的序號都是 0 )。但是,很明顯, Color.RED和Season.SPRING并不相等

  • 但是Java使用Enum

The method compareTo(Color) in the type Enum<Color> is not applicable for the arguments (Season)
  • 1
  • 他說明,compareTo方法只接受Enum類型

  • Java為了限定形態參數實例化的對象,故要求只能是Enum,這樣才能對 compareTo之類的方法所傳入的參數進行形態檢查。 因為“紅色”只有和“綠色”比較才有意義,用“紅色”和“春天”比較毫無意義,所以,Java用這種方式一勞永逸的保證像compareTo這樣的方法可以正常的使用而不用考慮類型

PS:在Java中,其實也可以實現“紅色”和“春天”比較,因為Enum實現了Comparable接口,可以重寫compareTo方法來實現不同的enum之間的比較

成員變量

  • 在Enum中,有兩個成員變量,一個是名字(name),一個是序號(ordinal)。 序號是一個枚舉常量,表示在枚舉中的位置,從0開始,依次遞增
/*** @author hollis*/ private final String name; public final String name() {return name; } private final int ordinal; public final int ordinal() {return ordinal; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

構造函數

  • 前面我們說過,Enum是一個抽象類,不能被實例化,但是他也有構造函數,從前面我們反編譯出來的代碼中,我們也發現了Enum的構造函數,在Enum中只有一個保護類型的構造函數:
protected Enum(String name, int ordinal) {this.name = name;this.ordinal = ordinal; }
  • 1
  • 2
  • 3
  • 4
  • 文章開頭反編譯的代碼中private Color(String s, int i) { super(s, i); }中的super(s, i);就是調用Enum中的這個保護類型的構造函數來初始化name和ordinal

其他方法

  • Enum當中有以下這么幾個常用方法,調用方式就是使用Color.RED.methodName(params…)的方式調用
public String toString() {return name; }public final boolean equals(Object other) {return this==other; }public final int hashCode() {return super.hashCode(); }public final int compareTo(E o) {Enum other = (Enum)o;Enum self = this;if (self.getClass() != other.getClass() && // optimizationself.getDeclaringClass() != other.getDeclaringClass())throw new ClassCastException();return self.ordinal - other.ordinal; }public final Class<E> getDeclaringClass() {Class clazz = getClass();Class zuper = clazz.getSuperclass();return (zuper == Enum.class) ? clazz : zuper; }public static <T extends Enum<T>> T valueOf(Class<T> enumType,String name) {T result = enumType.enumConstantDirectory().get(name);if (result != null)return result;if (name == null)throw new NullPointerException("Name is null");throw new IllegalArgumentException("No enum constant " + enumType.getCanonicalName() + "." + name); }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

參考資料

  • Java 7 源碼學習系列(二)——Enum

from:https://blog.csdn.net/qiuchengjia/article/details/52910948?

總結

以上是生活随笔為你收集整理的Java源码分析--Enum的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。