playground

枚举

我们先写一个简单的枚举类Human表示人类,里面有不同的枚举值代表不同肤色的人种。

enum Human {
    BLACK,
    WHITE,
    YELLOW;
}

对上面的代码进行编译后,使用JAD工具进行反编译,可以看到以下的代码。

final class Human extends Enum
{

    public static Human[] values()
    {
        return (Human[])$VALUES.clone();
    }

    public static Human valueOf(String s)
    {
        return (Human)Enum.valueOf(playground/Human, s);
    }

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

    public static final Human BLACK;
    public static final Human WHITE;
    public static final Human YELLOW;
    private static final Human $VALUES[];

    static
    {
        BLACK = new Human("BLACK", 0);
        WHITE = new Human("WHITE", 1);
        YELLOW = new Human("YELLOW", 2);
        $VALUES = (new Human[] {
            BLACK, WHITE, YELLOW
        });
    }
}

从上面可以看到Human类继承了Enum类,原本3个枚举值也变成了Human类的静态常量。

下面我们往Human类中加入一个构造方法。

enum Human {
    BLACK("Africa"),
    WHITE("America"),
    YELLOW("China");

    private String country;

    public String getCountry() {
        return country;
    }

    Human(String country) {
        this.country = country;
    }
}

对修改后的代码进行反编译,结果如下。

final class Human extends Enum
{

    public static Human[] values()
    {
        return (Human[])$VALUES.clone();
    }

    public static Human valueOf(String s)
    {
        return (Human)Enum.valueOf(playground/Human, s);
    }

    public String getCountry()
    {
        return country;
    }

    private Human(String s, int i, String s1)
    {
        super(s, i);
        country = s1;
    }

    public static final Human BLACK;
    public static final Human WHITE;
    public static final Human YELLOW;
    private String country;
    private static final Human $VALUES[];

    static
    {
        BLACK = new Human("BLACK", 0, "Africa");
        WHITE = new Human("WHITE", 1, "America");
        YELLOW = new Human("YELLOW", 2, "China");
        $VALUES = (new Human[] {
            BLACK, WHITE, YELLOW
        });
    }
}

可以看到,编译器自动修改了Human的构造方法中的参数。

我们更进一步,往Human类中增加一个抽象方法。

enum Human {
    BLACK() {
        @Override
        String getCountry() {
            return "Africa";
        }
    },
    WHITE() {
        @Override
        String getCountry() {
            return "America";
        }
    },
    YELLOW() {
        @Override
        String getCountry() {
            return "China";
        }
    };

    abstract String getCountry();
}

这时用javac编译后你会发现,除了Human.class文件,编译器还为每一种枚举值单独创建了一个匿名类,形如Human$1Human$2Human$3

这时候反编译的结果如下。

abstract class Human extends Enum
{

    public static Human[] values()
    {
        return (Human[])$VALUES.clone();
    }

    public static Human valueOf(String s)
    {
        return (Human)Enum.valueOf(playground/Human, s);
    }

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

    abstract String getCountry();

    public static final Human BLACK;
    public static final Human WHITE;
    public static final Human YELLOW;
    private static final Human $VALUES[];

    static
    {
        BLACK = new Human("BLACK", 0) {

            String getCountry()
            {
                return "Africa";
            }

        };

        WHITE = new Human("WHITE", 1) {

            String getCountry()
            {
                return "America";
            }

        };

        YELLOW = new Human("YELLOW", 2) {

            String getCountry()
            {
                return "China";
            }

        };

        $VALUES = (new Human[] {
            BLACK, WHITE, YELLOW
        });
    }
}

Human类自动加上了abstract修饰符,而3种枚举值以匿名类的方式重写了getCountry()方法。