Java基礎系列-Enum深刻解析

原創文章,轉載請標註出處:http://www.javashuo.com/article/p-sorpszpw-dx.htmlhtml

1、概述

枚舉就是一個語法糖效果。java

定義一個枚舉,其實就是定義一個繼承抽象類Enum的類。數組

瞭解了Enum,就能瞭解枚舉。this

2、Enum解析

2.1 接口

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {}

枚舉類實現了Comparable和Serializable接口,那麼也就意味着,每一個枚舉類都擁有比較(有序)和序列化功能。code

2.2 屬性

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    private final String name;
    private final int ordinal;
    public final String name() {
        return name;
    }
    public final int ordinal() {
        return ordinal;
    }    
}

這兩個屬性是枚舉的內置屬性,name表示的是枚舉值的名稱,ordinal表示的是枚舉值的序號。htm

其做用後面再說blog

2.3 構造器

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }
}

Enum中只有這一個構造器,其申明爲protected就是爲了繼承它的子類(咱們定義的各類枚舉)來調用的。繼承

2.4 equals方法

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    public final boolean equals(Object other) {
        return this==other;
    }
}

默認的equals方法底層就是使用==實現的,因此在枚舉的比較使用equals和==都是能夠的。前提是沒有在枚舉類中重寫equals方法。接口

咱們能夠在自定義的枚舉類中重寫該方法,來實現咱們本身的比較方式。字符串

2.5 禁用的功能

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    protected final Object clone() throws CloneNotSupportedException {
        throw new CloneNotSupportedException();
    }
    protected final void finalize() { }
    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");
    }   
}

這四個方法均是被禁用的方法:

  • 克隆:目的爲了保證單例惟一
  • finalize:禁用終引用
  • 序列化中禁用readObject和readObjectNoData方法:目的爲了保證單例惟一

    2.6 compareTo方法

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    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;
    }
}

這是實現了接口Comparable中的方法。用於定義比較的方式,能夠看出這裏是使用枚舉值的序號做爲比較條件的。

2.7 方法

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
    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);
    }
}

該方法的做用是獲取到指定枚舉類型中指定枚舉名稱的枚舉值。

3、枚舉的實現

枚舉是一種編譯器語法糖。

咱們使用enum關鍵字定義一個枚舉,編譯以後,編譯器會對其進行加工,具體以下:

  1. 編譯成爲class類型,並繼承自Enum
  2. 添加靜態的values方法,用於獲取全部枚舉值的數組
  3. 添加valueOf方法,實現Enum中的valueOf方法,能夠根據具體的枚舉值名稱字符串獲取對應的枚舉值
  4. 添加私有構造器,其中調用Enum中定義的惟一的構造器
  5. 定義靜態常量枚舉值
  6. 添加靜態塊爲這些靜態枚舉常量賦值

經過上面一些列加工以後,枚舉類被解析爲一個普通的類,類名不變。

相關文章
相關標籤/搜索