Java SEの基盤の統合(V):列挙

多くのプログラミング言語での列挙は、そのようなC / C ++のように、持っているが、JavaはJDK1.5だけでこんなに遅く、私にはわからない理由として、この特性を向上させるまで。その列挙は何ですか?ウィキペディアで以下の定義がありますで数学コンピュータ科学の理論、一連の列挙は、系列の有限集合、またはオブジェクト数の特定のタイプのすべてのメンバーのためのいくつかのプログラムのリストです。このような週日曜日、月曜日、火曜日、水曜日、の日と木曜日、金曜日、土曜日のように。

1 Javaの列挙型

使用するのは簡単1.1

Javaコンポーネントは、様々なクラスで、列挙も例外ではありません。ここに示すように、列挙型クラス、あなただけのenumキーワードに一般的なカテゴリを交換したいクラスのキーワードを作成するには:

public enum ColorEnum {

    RED("RED", 0),
    BLUE("BLUE", 1),
    BLACK("BLACK",2),
    WHITE("WHITE", 3);

    ColorEnum(String name, int code) {
        this.name = name;
        this.code = code;
    }

    private String name;

    private int code;

    //getter and setter
}
复制代码

列挙型クラスは、メンバ変数、コンストラクタ、インスタンスメソッド、静的メソッドを持つことができますが、唯一のコンストラクタは、外部プログラムがインスタンスを列挙構築するコンストラクタを使用することはできません。すなわち、唯一の赤など、クラスのインスタンス内に作成することができ、プライベートで(「RED」、0)の文言は、コンストラクタを呼び出しているのインスタンスを列挙作成し、この例では、いくつかの記事はシングルトンパターンを達成するために列挙体を使用することが最もけれども(最も簡単であると言う理由で、単一の場合、あります)悪いので可読性の、シンプルですが、最も実用的ではありません。クラスを作成し、次のコードは、列挙クラスの使用方法を示して使用してください:

public class Test {


    public static void main(String[] args) {
        System.out.println(ColorEnum.BLACK);        //直接调用实例
        System.out.println(ColorEnum.BLACK.getName()); //调用实例的getName()方法
        System.out.println(ColorEnum.BLACK.getCode()); //调用实例的getCode()方法
        System.out.println(ColorEnum.valueOf("BLACK")); //valueOf()方法根据枚举的名字获取枚举实例

        System.out.println("----------------------------");
        for (ColorEnum colorEnum : ColorEnum.values()) {  //values()方法返回该枚举类的所有枚举实例
            System.out.println(colorEnum.getName());
            System.out.println(colorEnum.ordinal());    //ordinal返回该枚举实例在枚举类中声明的顺序,从0开始
        }
    }
}

复制代码

より明確に書かれた注意事項は、パラメータのみを受け付けている混乱のvalueOf(String)メソッドは、列挙インスタンスの名前で、ここに注意を払うことは名前がメンバ変数名を参照ではなく、インスタンス自体の名前、たとえばでColorEnumでRED(「RED」、0)ステートメントは、最も外側のREDは、インスタンス自体の名前であり、列挙クラスのちょうどメンバ変数文字列「RED」は、それはここでは関係ありません理解していない、ので、ソースコードを見ていきます私が理解するとき。

抽象メソッド1.2列挙

単に外の使用に加えて、我々はまた、列挙クラス、抽象メソッドに参加することができ、この抽象メソッドの各インスタンスは、それ以外の場合は、次のようにコンパイルに失敗し、実装する必要があります。

//其他代码和原先完全一样
RED("RED", 0) {
    @Override
    public void abstractMethod() {
        System.out.println("RED's method");
    }
},
BLUE("BLUE", 1) {
    @Override
    public void abstractMethod() {
        System.out.println("BLUE's method");
    }
},
BLACK("BLACK",2) {
    @Override
    public void abstractMethod() {
        System.out.println("BLACK's method");
    }
},
WHITE("WHITE", 3) {
    @Override
    public void abstractMethod() {
        System.out.println("WHITE's method");
    }
};

public abstract void abstractMethod();
复制代码

コードはabstractMethod()抽象メソッドを宣言し、各列挙インスタンスは、このメソッドを実装し、各インスタンスを列挙しなければならない症状の列挙クラスの柔軟性である独自の実装を持つことができます。この機能は、四則演算、次に、差分演算は、それらの異なる動作特性に応じて達成することができる2つのパラメータを有し、抽象メソッドを、列挙表すために使用されるクラスが存在する場合など、いくつかのシナリオにおいて非常に有用です。

列挙それは言っても過言ではありませんこれは、まだ柔軟な使い方がたくさんあります。

2列挙型クラスの分解能

列挙型クラスは、すべての列挙クラスの親クラスであり、かつ比較可能Serializableインタフェースを実装し、比較可能と直列化可能にする能力を持っています。そのソースコードを以下に示します。

public abstract class Enum<E extends Enum<E>>
        implements Comparable<E>, Serializable {
   
    //name字段表示枚举实例的名字
    private final String name;

    public final String name() {
        return name;
    }
	
	//ordinal字段表示枚举实例在枚举类中声明的顺序,从0开始
    private final int ordinal;
    
    public final int ordinal() {
        return ordinal;
    }
    
    //构造器
    protected Enum(String name, int ordinal) {
        this.name = name;
        this.ordinal = ordinal;
    }

    public String toString() {
        return name;
    }

    public final boolean equals(Object other) {
        return this==other;
    }

    public final int hashCode() {
        return super.hashCode();
    }

	//默认不支持clone
    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;
    }

    @SuppressWarnings("unchecked")
    public final Class<E> getDeclaringClass() {
        Class<?> clazz = getClass();
        Class<?> zuper = clazz.getSuperclass();
        return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)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);
    }

    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");
    }
}

复制代码

2つのメンバ変数名と序数を見てみましょう、名前は前述の列挙インスタンスの名前で、序列挙順は0から始まる、列挙クラスのインスタンスで宣言されています。そして、クラスオブジェクト名のインスタンスを列挙し、インスタンスを列挙するために基づいて対応する列挙インスタンスを取得するためのvalueOf()メソッドがあり、我々はあなたが列挙クラスを作成するときので、enumTypeに合格しなかった使用された場合、私たちは、ヘビーデューティーバージョンに入社ヘルプJava、我々は一般的に大型バージョンを使用します。最後に、readObjectメソッド()メソッドを見て、デフォルトでは、列挙インスタンスをシリアライズすることができますが、デフォルトでは、readObjectメソッドを呼び出したときに、逆シリアル化は、このメソッドは直接例外をスローするため、直列化復元することはできません直列化復元を停止し、我々は非直列化されたオーバーライドすることによって、このメソッドをスイッチを開いたが、気をつけて、単一の実施形態の直列化復元操作の特性を列挙例を破壊する可能性があるので、それは仮想マシンの列挙を引き起こす可能性がありますすることができます例では、一意ではありません。

このようのcompareTo、同じような他の方法言うことではないものを、それはすべてのルーチンです。

3まとめ

列挙は、非常に強力で柔軟性の非常に重要な要素であるが、多くの開発者は彼を見下すが、それは一部だけ列挙定数の声明であると思うかもしれません。これは、本当に列挙の最も基本的な役割であるが、実際には、Javaの列挙、他の多くの強力な機能がありますが、例えば、抽象メソッドを宣言することができ、我々は簡単そうで、スレッドの安全性を保証する一つのケースを確認し、することができます。

おすすめ

転載: juejin.im/post/5d6e80905188251ff57fa172