深入理解java枚举

       枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类(class)类型却又比类类型多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。

1.定义枚举及应用场景

        例如季节,只有春夏秋冬。如果你创建了一个season类,你当然有义务维护这个类的实例对象只能是春(SPRING)、夏(SUMMER)、秋(AUTUMN)、冬(WINTER)这四个。这个时候就体现出枚举类的作用了,java中枚举类型就是针对这样的场景需求所设计的。在jdk1.5以前我们是这样定义的:

public class SeasonConstant {

    private final static String SPRING = "SPRING";
    private final static String SUMMER = "SUMMER";
    private final static String AUTUMN = "AUTUMN";
    private final static String WINTER = "WINTER";
}

       上述代码中使我们常用的常量枚举类,该类这样定义本没有什么错误,但它存在许多不足,如在类型安全和使用方便性上并没有多少好处,如果存在定义int值相同的变量,混淆的几率还是很大的,编译器也不会提出任何警告。因此在jdk1.5以后便不提倡我们这样定义枚举,如下定义四季的常量:

/**
 * 枚举类的后缀建议为Enum,枚举类型的实例对象建议全大写(这样做符合JAVA的规范)
 */
public enum SeasonEnum{  
  SPRING,SUMMER,AUTUMN,WINTER
}

       如上代码定义枚举,比起使用class定义枚举代码更加简洁,与class关键字类似,只不过前者是定义枚举类型,后者是定义类类型。注意枚举中变量一般字母都大写多个值之间以逗号分隔。枚举可以像class类型一样定义在其他类的内部,同时也可以作为一个单独的文件存在即enum。

1.1枚举使用场景

public class EnumDemo {
    public static void main(String[] args) {
        SeasonEnum spring = SeasonEnum.SPRING;
        System.out.println(spring);
    }

    public enum SeasonEnum{
        SPRING,SUMMER,AUTUMN,WINTER
    }
}

如上述直接引用枚举即可。

1.2枚举实现原理

       既然可以像使用普通的类一样使用枚举,编译器究竟为我们做了些什么事呢?要想知道这其中的秘密,最有效的途径就是查看生成的字节码。通过javac反编译我们的类:

       通过编译后生成EnumDemo.class以及EnumDemo$SeasonEnum.class文件,查看文件我们可以知道EnumDemo.class为我们的枚举类,这也就验证前面所说的使用关键字enum定义枚举类型并编译后,编译器会自动帮助我们生成一个与枚举相关的类。通过反编译我们EnumDemo.class可以知道:

final class SeasonEnum extends Enum
{
    //编译器为我们添加的静态的values()方法
    public static SeasonEnum[] values()
    {
        return (SeasonEnum[])$VALUES.clone();
    }
    //编译器为我们添加的静态的valueOf()方法,注意间接调用了Enum也类的valueOf方法
    public static SeasonEnum valueOf(String s)
    {
        return (SeasonEnum)Enum.valueOf(com/dylan/SeasonEnum, s);
    }
    //私有构造函数
    private SeasonEnum(String s, int i)
    {
        super(s, i);
    }
     //前面定义的4种枚举实例
    public static final SeasonEnum SPRING;
    public static final SeasonEnum SUMMER;
    public static final SeasonEnum AUTUMN;
    public static final SeasonEnum WINTER;
    private static final SeasonEnum $VALUES[];

    static 
    {    
        //实例化枚举实例
        SPRING = new SeasonEnum("SPRING", 0);
        SUMMER = new SeasonEnum("SUMMER", 1);
        AUTUMN = new SeasonEnum("AUTUMN", 2);
        WINTER = new SeasonEnum("WINTER", 3);
        $VALUES = (new SeasonEnum[] {
                SPRING,
                SUMMER,
                AUTUMN,
                WINTER
        });
    }
}

       可以看到,一个枚举在经过编译器编译过后,变成了一个抽象类,它继承了java.lang.Enum;而枚举中定义的枚举常量,变成了相应的public static final属性,而且其类型就抽象类的类型,除此之外,编译器还帮助我们生成了4个SeasonEnum类型的实例对象分别对应枚举中定义的4个季节,这也充分说明了我们前面使用关键字enum定义的SeasonEnum类型中的每种季节枚举常量也是实实在在的SeasonEnum实例对象,只不过代表的内容不一样而已。注意编译器还为我们生成了两个静态方法,分别是values()和 valueOf(),稍后会分析它们的用法,到此我们也就明白了,使用关键字enum定义的枚举类型,在编译期后,也将转换成为一个实实在在的类,而在该类中,会存在每个在枚举类型中定义好变量的对应实例对象,如上述的SPRING枚举类型对应public static final SeasonEnum SPRING;,同时编译器会为该类创建两个方法,分别是values()和valueOf()。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值