深入淺出 Java 中列舉的實現原理

恆生LIGHT雲社群發表於2021-12-14

作者:幻好

來源: 恆生LIGHT雲社群

Java 中的列舉— Enum 的全稱為 Enumeration, 在 JDK 1.5 時就引入的特性,透過 java.lang 包中呼叫。

基本概述

在 JDK1.5 之前,透過定義常量使用的都是: public static fianl 。而列舉的設計,就是把相關的常量分組到一個列舉型別裡,方便建立和管理。

比如我們要定義一個顏色常量:


public 
enum 
Colour {

    REDYELLOWBLUEGREEN
}

這段程式碼透過底層編譯後,實際建立了4個列舉物件:


new 
Enum
<
EnumTest
>(
"RED"0);

new  Enum < EnumTest >( "YELLOW"1);
new  Enum < EnumTest >( "BLUE"2);
new  Enum < EnumTest >( "GREEN"3);

使用方式

條件選擇

enum 能透過 switch 方法進行簡單條件判斷


Colour 
color 
= 
Colour.
RED;

switch ( color) {
    case  RED:
        System. out. println( "紅色");
        break;
    case  YELLOW:
        System. out. println( "黃色");
        break;
    case  GREEN:
        System. out. println( "綠色");
        break;
    case  BLUE:
        System. out. println( "藍色");
        break;
    default:
        System. out. println( color);
        break;
}

迴圈遍歷

透過迴圈遍歷 .values() 能夠取到物件中的值


for (
Colour 
e : 
Colour.
values()) {

    System. out. println( e. toString());
}

集合對映

在我們使用列舉型別作為集合的型別或對映中的鍵的型別時,可以使用專門且高效的集合和對映實現。如: java.util.EnumSet java.util.EnumMap


// EnumSet的使用

EnumSet < Colour >  colorSet  =  EnumSet. allOf( Colour. class);
for ( Colour  color :  colorSet) {
    System. out. println( color);
}

// EnumMap的使用
EnumMap < ColourString >  colorMap  =  new  EnumMap( Colour. class);
colorMap. put( Colour. RED"紅色");
colorMap. put( Colour. YELLOW"黃色");
colorMap. put( Colour. GREEN"綠色");
colorMap. put( Colour. BLUE"藍色");

Set < Map. Entry < ColourString >>  colorEntries  =  colorMap. entrySet();
for ( Map. Entry < ColourString >  entry :  colorEntries) {
    System. out. println( entry. getKey(). name()  +  ":"  +  entry. getValue());
}

常用方法

透過   java.lang.Enum 類的原始碼,可以探索下列舉常用的一些方法和設計思想:

public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
// Enum 唯一的建構函式,由於 protected 修飾,所以不能呼叫這個建構函式。 它供編譯器為響應列舉型別宣告而發出的程式碼使用。

protected Enum(String name, int ordinal) {
  this.name = name;
  this.ordinal = ordinal;
}
```
// 返回此列舉常量的名稱,與在其列舉宣告中宣告的完全相同。
public final String name() {
  return name;
}
```
// 返回此列舉常量的序數(它在列舉宣告中的位置,其中初始常量被分配零序數)。(但大多數程式設計師不會使用這種方法)
public final int ordinal() {
  return ordinal;
}
```
// 與指定的物件進行比較以進行排序,當此物件小於、等於或大於指定物件時,返回一個負整數、零或正整數。且只能與相同列舉型別的其他列舉常量進行比較。 
public final int compareTo(E o) {
  Enum<?> other = (Enum<?>)o;
  Enum<E> self = this;
  if (self.getClass() != other.getClass() 
      self.getDeclaringClass() != other.getDeclaringClass())
      throw new ClassCastException();
  return self.ordinal - other.ordinal;
}
```
// 返回與此列舉常量的列舉型別對應的 Class 物件。
public final Class<E> getDeclaringClass() {
  Class<?> clazz = getClass();
  Class<?> zuper = clazz.getSuperclass();
  return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
```

}




## 底層原理

`enum` 的語法結構可能對於正常的 Java 看起來怪怪的,但是透過編譯器編譯後產生的是一個 `.class` 檔案, 可以理解列舉的語法結構是一種規範,使編譯器能識別並轉化為相應的類,底層實際上還是 `class` 。

```java
public class com.project.demo.Colour extends java.lang.Enum{
  public static final com.project.demo.Colour RED;
  public static final com.project.demo.Colour YELLOW;
  public static final com.project.demo.Colour BLUE;
  public static final com.project.demo.Colour GREEN;
  static {};
}

總結

所以 enum 實際上在 Java 只是一個類的形式存在,它能夠更加方便的幫助我們定義常量物件,並且支援定義屬性和方法,在一定程度上提高了我們的程式設計效率。

但是在使用時需要注意, enum 不能支援繼承,應該它已經繼承了包裡的 java.lang.Enum 類,所以在程式設計時我們需要考慮到。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70001864/viewspace-2847631/,如需轉載,請註明出處,否則將追究法律責任。

相關文章