Java Enumマルチステート


詳細
 
Enum多態、私は間違っていませんが、Enumは継承されてはいけません.他の人から継承されてはいけません.ただインタフェースを実現することができます.多態とは何ですか.しかし、まず「現象」を見てみましょう.
Javaコード
 public enum Fruit {  
    APPLE, PEAR, PEACH, ORANGE;  
 }
 
以上は簡単なenumですが、それについて補足します.Fruitはjava.lang.Enumのサブクラスです.正確には、Enumのサブクラスです.ここには継承関係が現れていますが、この継承はコンパイラが手伝ってくれたので、明示的にはできません.信じないならエンムの引用でAPPLEを指してみてもいいです.きっと大丈夫です.もうやってみません.これをより直感的に説明するために、Fruitの逆コンパイル結果を見てみましょう.
 
 
package test;

public final class Fruit extends Enum {

    private Fruit(String s, int i) {
        super(s, i);
    }

    public static Fruit[] values() {
        Fruit afruit[];
        int i;
        Fruit afruit1[];
        System.arraycopy(afruit = ENUM$VALUES, 0,
                afruit1 = new Fruit[i = afruit.length], 0, i);
        return afruit1;
    }

    public static Fruit valueOf(String s) {
        return (Fruit) Enum.valueOf(test / Fruit, s);
    }

    public static final Fruit APPLE;
    public static final Fruit PEAR;
    public static final Fruit PEACH;
    public static final Fruit ORANGE;
    private static final Fruit ENUM$VALUES[];

    static {
        APPLE = new Fruit("APPLE", 0);
        PEAR = new Fruit("PEAR", 1);
        PEACH = new Fruit("PEACH", 2);
        ORANGE = new Fruit("ORANGE", 3);
        ENUM$VALUES = (new Fruit[] { APPLE, PEAR, PEACH, ORANGE });
    }
}

 
これらの行に注意してください.
 
 
public static final Fruit APPLE;  
public static final Fruit PEAR;  
public static final Fruit PEACH; 
public static final Fruit ORANGE;

 
JDK Enumの実現は、Effective Javaで提案されているTypeSafeEnumモードを踏襲したにすぎず、コンパイラやJVMなどより下位レベルでのサポートにすぎないようです.ここまで、少なくともFruitとEnumの継承関係を説明したが、問題は、今はFruitから子供を派遣し続けることができないのに、どこからの多態なのかということだ.もっとコードを書きましょう.
 
 
public enum Fruit {
    APPLE {

        public void test() {
            System.out.println("I am an apple.");
        }
    },
    PEAR {

        public void test() {
            System.out.println("I am a pear.");
        }
    },
    PEACH {

        public void test() {
            System.out.println("I am a peach.");
        }
    },
    ORANGE;

    public void test() {
        System.out.println("I am a fruit.");
    }
}

public enum Fruit {
    APPLE {

        public void test() {
            System.out.println("I am an apple.");
        }
    },
    PEAR {

        public void test() {
            System.out.println("I am a pear.");
        }
    },
    PEACH {

        public void test() {
            System.out.println("I am a peach.");
        }
    },
    ORANGE;

    public void test() {
        System.out.println("I am a fruit.");
    }
}

 
 
 
このうち、OrangeだけがOveride test()メソッドを持たない.メイン関数で呼び出します.
 
public static void main(String[] args) {  
        Fruit.APPLE.test();  
        Fruit.PEAR.test();  
        Fruit.PEACH.test();  
        Fruit.ORANGE.test();  
    }   public static void main(String[] args) {
        Fruit.APPLE.test();
        Fruit.PEAR.test();
        Fruit.PEACH.test();
        Fruit.ORANGE.test();
    } 

  
 
出力結果:
参照
I am an apple. I am a pear. I am a peach. I am a fruit.
 
testメソッドを再定義したAPPLE,PEAR,PEACHは親から継承されたデフォルトの動作を上書きし,testメソッドを新たに定義しないORANGEは親の動作を踏襲し,多態性がここで示されている.では、私たちはさっきFruitの反コンパイル結果を見たことがあるのに、Fruitから新しいクラスが継承されていないのを見たことがありますが、これらの多態行為はどこから出てきたのでしょうか.それが「多態」だと言うのは正しいのだろうか.実は、Fruitクラスはこの時点で微妙な変化が発生しており、すべてJDKのEnumの実現に関係しています.コンパイル結果ディレクトリの下を見てみましょう.
どうしてFruit.classのほかに、内部クラスのようなclassファイルがいくつか増えたのですか?ここを見て少し手がかりがあるかもしれませんが、この時に反コンパイルの結果を見て、何をしているのか見てみましょう.