我看JAVA 之 枚舉類型
注:基于jdk11
Enum
Enum是Java(1.5+)中所有枚舉類型的公共基類。有關枚舉的更多資訊,包括編譯器合成的隐式聲明方法的描述,可以在Java™語言規範的
[第8.9節](https://docs.oracle.com/javase/specs/jls/se11/html/jls-8.html#jls-8.9)中找到。
當使用枚舉類型作為Set中的元素或Map中的key時,可以使用專用且高效的java.util.EnumSetjava.util.EnumMap實作。
定義一個枚舉類,隐式繼承了java.lang.Enum類(是以枚舉類隻能去實作接口不能顯式繼承其他類),見如下代碼塊:
enum Color {//
RED, GREEN, BLANK, YELLOW
}
實作了如下幾個接口
1. Comparable
2. Serializable
源碼分析:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
/**
* accessing this field.枚舉常量名稱,通路名稱時,最好使用toString()方法而不是直接通路name字段。
*/
private final String name;
/**
* 枚舉常量名稱,通路名稱時,最好使用toString()方法而不是此方法。
*/
public final String name() {
return name;
}
/**
* 枚舉常量在枚舉類中定義的次序,次序從0開始。開發人員很少用到這個字段。此字典被設計用來在基于枚舉類型的複雜資料結構中,如 java.util.EnumSet 和 java.util.EnumMap。
*
*/
private final int ordinal;
public final int ordinal() {
return ordinal;
}
/**
* Sole constructor. Programmers cannot invoke this constructor.
* It is for use by code emitted by the compiler in response to
* enum type declarations.
* 唯一的構造器。開發人員不能調用這個構造函數。它由編譯器調用以響應枚舉類型的聲明。
*/
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
/**
* 預設傳回枚舉常量的名字,此方法可以被覆寫以便傳回更加友好name。
*
* @return the name of this enum constant
*/
public String toString() {
return name;
}
/**
* Returns true if the specified object is equal to this
* enum constant.
*
* @param other the object to be compared for equality with this object.
* @return true if the specified object is equal to this
* enum constant.
*/
public final boolean equals(Object other) {
return this==other;
}
public final int hashCode() {
return super.hashCode();
}
/**
* 枚舉類型不可以克隆,以保持其單例性。
* @return (never returns)
*/
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
/**
* 比較算法是比較枚舉常量的次序。
*/
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
/**
* 傳回枚舉常量對應的類對象。如果兩個枚舉常量調用getDeclaringClass()值相等,name這兩個枚舉對象的枚舉類型相同。
*/
@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
/**
* 傳回指定枚舉類型和名稱的枚舉常量。參數name一定要與指定枚舉類型的常量名稱相同(多餘的空白字元也是不被允許的)。
*/
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);
}
/**
* 枚舉類沒有 finalize()
*/
@SuppressWarnings("deprecation")
protected final void finalize() { }
/**
* prevent default deserialization
*/
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
throw new InvalidObjectException("can't deserialize enum");
}
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("can't deserialize enum");
}
}
适用原則 :
枚舉在什麼地方适用呢?一條普遍規則是,任何使用常量的地方,例如目前用 switch 代碼切換常量的地方。如果隻有單獨一個值(例如,鞋的最大尺寸,或者籠子中能裝猴子的最大數目),則還是把這個任務留給常量吧。但是,如果定義了一組值,而這些值中的任何一個都可以用于特定的資料類型,那麼将枚舉用在這個地方最适合不過。
例子:
package chapter03;
public class TestEnum {
public static void main(String [] args) {
System.out.println(Color.RED);
System.out.println(Color.RED.name());
System.out.println(Color.RED.ordinal());
System.out.println(Color.class);
System.out.println(Color.class.isEnum());
System.out.println(Color.RED.getDeclaringClass());
System.out.println("--- Class.getEnumConstants() ---");
for (Color color: Color.RED.getClass().getEnumConstants()) {
System.out.println(color);
}
System.out.println("--- interface enhance ---");
System.out.println(Color.RED.info());
System.out.println("--- switch clause ---");
System.out.println(swithColor(Color.RED));
System.out.println("--- Enum.valueOf() ---");
System.out.println(Enum.valueOf(Color.class, "YELLOW"));
System.out.println(Enum.valueOf(Color.class, " YELLOW"));
}
public static Color swithColor(Color color) {
switch (color) {
case RED : return Color.GREEN;
case GREEN : return Color.YELLOW;
case YELLOW : return Color.RED;
default: return Color.GREEN;
}
}
}
interface ColorInterface {
String info();
}
enum Color implements ColorInterface{
RED, GREEN, YELLOW;
@Override
public String info() {
return name() + "'s info";
}
}
列印結果如下:
RED
RED
0
class chapter03.Color
true
class chapter03.Color
--- Class.getEnumConstants() ---
RED
GREEN
YELLOW
--- interface enhance ---
RED's info
--- switch clause ---
GREEN
--- Enum.valueOf() ---
YELLOW
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant chapter03.Color.
at java.base/java.lang.Enum.valueOf(Enum.java:240)
at chapter03.TestEnum.main(TestEnum.java:21)