Enum枚举类型
Enum的全写是Enumeration,这个词的翻译是列举、逐条陈述、细目。在程序语言中,枚举类型是一种特殊的数据类型(常用的数据类型比如字符串、整型),这种数据类型的变量值限定在固定的范围, 比如季节只有春夏秋冬,月份是12个。
Java中的枚举
枚举前时代
在Java语言中, 枚举类型从JDK1.5才开始提供。在这之前使用接口静态常量来实现相关功能(也可以是类静态常量),以季节为例:在不使用枚举类之前,一般使用接口静态常量实现。比如:
public interface Season {
public static final int SPRING = 1;
public static final int SUMMER = 2;
public static final int AUTUMN = 3;
public static final int WINTER = 4;
}
使用JUnit使用测试如下:
@Test
public void noEnum() {
int i = 1;
Assert.assertTrue(Season.SPRING == i);
}
使用接口静态常量的方式比较难限定变量的范围,而且定义繁琐,功能也很有限,于是在Java 1.5 中定义了一个枚举类型:java.lang.Enum
Java枚举的定义
类似类(class)和接口(interface)的定义,Java提供enum关键字用来定义枚举类,同样定义一个季节的枚举类, 代码可以简洁如下:
public enum Season {
SPRING, SUMMER, AUTUMN, WINTER
}
在枚举类中直接列出常量,常量遵循全部大写的规则。在上面的枚举类示例代码中,SPRING,SUMMER,AUTUMN,WINTER 是Season的成员。
枚举成员默认是public、static 、final(所以可以使用Season.SPRING方式调用枚举成员)每一个枚举类型成员都可以看作是枚举类的实例 (Season.SPRING的类型也是Season),在JUnit使用测试如下:
@Test
public void enumBase() {
Season season = Season.SPRING;
Assert.assertTrue(season.equals(Season.SPRING));
}
Java 枚举类的特性
Java枚举类的特性有:
- 枚举成员是public、static 和 final。
- 枚举可以实现接口,但不能继承接口。
- 枚举类是final的,所以不能继承。
- 枚举类的构造方法是私有的。
- 枚举成员是枚举类的实例。
但是从上面Season枚举类的定义来看,完全看不出这些特性,这些特性是怎么来的呢? 请看下面的原理探求。
Java枚举类实现的原理探求
java枚举类型的奥秘就在编译阶段,枚举类在编译后会生成了一个扩展java.lang.Enum的类。这个可以通过反编译工具反编译生成的.class文件。对上面的生成的Season.class文件进行反编译:
package com.qjwy.system.util;
public final class Season extends Enum {
private Season(String s, int i) {
super(s, i);
}
public static Season[] values() {
Season aseason[];
int i;
Season aseason1[];
System.arraycopy(aseason = ENUM$VALUES, 0, aseason1 = new Season[i = aseason.length], 0, i);
return aseason1;
}
public static Season valueOf(String s) {
return (Season) Enum.valueOf(util/Season, s);
}
public static final Season SPRING;
public static final Season SUMMER;
public static final Season AUTUMN;
public static final Season WINTER;
private static final Season ENUM$VALUES[];
static {
SPRING = new Season("SPRING", 0);
SUMMER = new Season("SUMMER", 1);
AUTUMN = new Season("AUTUMN", 2);
WINTER = new Season("WINTER", 3);
ENUM$VALUES = (new Season[] { SPRING, SUMMER, AUTUMN, WINTER });
}
}
从反编译后的源码可以看出:
- 自定义的枚举类会自动继承java.lang.Enum类
- 每个成员变量都会被转换为 public static final的枚举类型的实例
- 自动添加private的构造函数
从反编译后的源码就不难理解Enum的特性了