程序员码农的世界程序园

深入理解枚举类型

2019-06-11  本文已影响63人  山东大葱哥

枚举

Java的枚举类型,关键字enum,全称为 enumeration,从Java 5.0 开始提供了的一种新类型。

示例

public enum EnumTest {
    FIRST, SECOND, THIRD, FOURTH, FIFTH;
}

通过enum关键字命名,内部写枚举变量。

反编译

注意:这里使用的反编译工具在资料中单独提供,常规的反编译工具会直接反编译为enum。

enum 的语法结构尽管和 class 的语法不一样,但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum<E>。

public final class EnumTest extends Enum
{
    //返回存储枚举实例的数组的副本。values()方法通常用于foreach循环遍历枚举常量。
    public static EnumTest[] values()
    {
        return (EnumTest[])$VALUES.clone();
    }
    
    //根据实例名获取实例
    public static EnumTest valueOf(String name)
    {
        return (EnumTest)Enum.valueOf(com/boxuegu/intermediate/language/sugar/enumtest/EnumTest, name);
    }
    
    //私有构造方法,这里调用了父类的构造方法,其中参数s对应了常量名,参数i代表枚举的一个顺序(这个顺序与枚举的声明顺序对应,用于oridinal()方法返回顺序值)
    private EnumTest(String s, int i)
    {
        super(s, i);
    }

     //我们定义的枚举,在这里声明了五个EnumTest的常量对象引用,对象的实例化在static静态块中
    public static final EnumTest FIRST;
    public static final EnumTest SECOND;
    public static final EnumTest THIRD;
    public static final EnumTest FOURTH;
    public static final EnumTest FIFTH;
    //将所有枚举的实例存放在数组中
    private static final EnumTest $VALUES[];

    static 
    {
        //实例化常量对象
        FIRST = new EnumTest("FIRST", 0);
        SECOND = new EnumTest("SECOND", 1);
        THIRD = new EnumTest("THIRD", 2);
        FOURTH = new EnumTest("FOURTH", 3);
        FIFTH = new EnumTest("FIFTH", 4);
        //将所有枚举的实例存放在数组中
        $VALUES = (new EnumTest[] {
            FIRST, SECOND, THIRD, FOURTH, FIFTH
        });
    }
}

深入理解枚举

  1. 枚举的父类

    通过上面的反编译后代码,我们可以看到public final class EnumTest extends Enum,说明该类是继承了Enum类的,同时final关键字告诉我们,这个类是不能被继承的。当我们使用enmu来定义一个枚举类型的时候,编译器会自动帮我们创建一个final类型的类继承Enum类,所以枚举类型不能被继承。

  2. 构造方法

    私有构造方法,这里调用了父类的构造方法protected Enum(String name, int ordinal),其中参数s对应了常量名name,参数i代表枚举的一个顺序ordinal,这个顺序与枚举的声明顺序对应,用于oridinal()方法返回顺序值。

  3. 常量对象

    我们定义的枚举类型在反编译后的代码中,对应了五个EnumTest的常量对象引用。

    这五个对象使用static静态块中的方式进行实例化,FIRST = new EnumTest("FIRST", 0);,可以看到使用了私有构造方法进行了实例化,每个值的名称都被转换成一个字符串,而顺序就是我们定义枚举的声明顺序(从0开始)。

使用场景

可以替代常量类,在没有枚举之前,一般使用如下形式定义一些常量:

public interface Order {
    String FIRST = "FIRST";
    String SECOND = "SECOND";
    String THIRD = "THIRD";
    String FOURTH = "FOURTH";
}

枚举扩展(自定义属性和方法)

既然enum枚举类型在经过编译器后,被编译成了一个普通类, 那么可以把 enum 看成是一个普通的 class,于是我们可以对其定义一些属性和方法,不同之处是:enum 不能使用 extends 关键字继承其他类,因为 enum 已经继承了 java.lang.Enum(java是单一继承)。

public enum EnumTest2 {
    FIRST(1), SECOND(2), THIRD(3), FOURTH(4), FIFTH(5);
    private int value;

    /**
     * 带一个参数的构造函数
     *
     * @param value
     */
    private EnumTest2(int value) {
        this.value = value;
    }


    public int getValue() {
        return value;
    }

    public static void main(String[] args) {
        System.out.println("EnumTest.FRI 的 value = " + EnumTest2.FIRST.getValue());
    }
}

枚举对象的常用方法介绍

int compareTo(E o)
比较此枚举与指定对象的顺序。

Class<E> getDeclaringClass()
返回与此枚举常量的枚举类型相对应的 Class 对象。

String name()
返回此枚举常量的名称,在其枚举声明中对其进行声明。

intordinal()`
返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。

String toString()

​ 返回枚举常量的名称,它包含在声明中。

static <T extends Enum<T>> T valueOf(Class<T> enumType, String name)
返回带指定名称的指定枚举类型的枚举常量。

上一篇 下一篇

猜你喜欢

热点阅读