在编程语言中我们,都会接触到枚举类型,通常我们进行有穷的列举来实现一些限定。Java也不例外。Java中的枚举类型为Enum,本文将对枚举进行一些比较深入的剖析。

什么是Enum

Enum是自Java 5 引入的特性,用来方便Java开发者实现枚举应用。一个简单的Enum使用如下。

// ColorEnum.javapublic enum ColorEmun {    RED,    GREEN,    YELLOW}public void setColorEnum(ColorEmun colorEnum) {    //some code here}setColorEnum(ColorEmun.GREEN);

为什么会有Enum

在Enum之前的我们使用类似如下的代码实现枚举的功能.

public static final int COLOR_RED = 0;public static final int COLOR_GREEN = 1;public static final int COLOR_YELLOW = 2;public void setColor(int color) {    //some code here}//调用setColor(COLOR_RED)

然而上面的还是有不尽完美的地方

  • setColor(COLOR_RED)与setColor(0)效果一样,而后者可读性很差,但却可以正常运行
  • setColor方法可以接受枚举之外的值,比如setColor(3),这种情况下程序可能出问题

概括而言,传统枚举有如下两个弊端

  • 安全性
  • 可读性,尤其是打印日志时

因此Java引入了Enum,使用Enum,我们实现上面的枚举就很简单了,而且还可以轻松避免传入非法值的风险.

枚举原理是什么

Java中Enum的本质其实是在编译时期转换成对应的类的形式。

首先,为了探究枚举的原理,我们先简单定义一个枚举类,这里以季节为例,类名为Season,包含春夏秋冬四个枚举条目.

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

然后我们使用javac编译上面的类,得到class文件.

javac Season.java

然后,我们利用反编译的方法来看看字节码文件究竟是什么.这里使用的工具是javap的简单命令,先列举一下这个Season下的全部元素.

company javap SeasonWarning: Binary file Season contains com.company.SeasonCompiled from "Season.java"public final class com.company.Season extends java.lang.Enum<com.company.Season> {  public static final com.company.Season SPRING;  public static final com.company.Season SUMMER;  public static final com.company.Season AUTUMN;  public static final com.company.Season WINTER;  public static com.company.Season[] values();  public static com.company.Season valueOf(java.lang.String);  static {};}

从上反编译结果可知

  • java代码中的Season转换成了继承自的java.lang.enum的类
  • 既然隐式继承自java.lang.enum,也就意味java代码中,Season不能再继承其他的类
  • Season被标记成了final,意味着它不能被继承

static代码块

使用javap具体反编译class文件,得到静态代码块相关的结果为

static {};    Code:       0: new