Java从JDK1.5开始支持枚举,也就是说,Java一开始是不支持枚举的,就像泛型一样,都是JDK1.5才加入的新特性。通常一个特性如果在一开始没有提供,在语言发展后期才添加,会遇到一个问题,就是向后兼容性的问题。像Java在1.5中引入的很多特性,为了向后兼容,编译器会帮我们写的源代码做很多事情,比如泛型为什么会擦除类型,为什么会生成桥接方法,foreach迭代,自动装箱/拆箱等,这有个术语叫“语法糖”,而编译器的特殊处理叫“解语法糖”。那么像枚举也是在JDK1.5中才引入的,又是怎么实现的呢?
Java在1.5中添加了java.lang.Enum抽象类,它是所有枚举类型基类。提供了一些基础属性和基础方法。同时,对把枚举用作Set和Map也提供了支持,即java.util.EnumSet和java.util.EnumMap。
如何定义枚举类型
比如表示加减乘除操作,我们可以定义如下枚举:
package com.mikan;
/**
* @author Mikan
* @date 2015-08-29 12:06
*/
public enum Operator {
ADD,
SUBTRACT,
MULTIPLY,
DIVIDE
}
上面的枚举定义了四个枚举常量,同时,在枚举中还可以定义普通方法、抽象方法,如下所示:
package com.mikan;
/**
* @author Mikan
* @date 2015-08-29 12:06
*/
public enum Operator {
ADD {
@Override
public int calculate(int a, int b){
return a + b;
}
},
SUBTRACT {
@Override
public int calculate(int a, int b){
return a - b;
}
},
MULTIPLY {
@Override
public int calculate(int a, int b){
return a * b;
}
},
DIVIDE {
@Override
public int calculate(int a, int b){
if (b == 0) {
throw new IllegalArgumentException("divisor must not be 0");
}
return a / b;
}
};
public abstract int calculate(int a, int b);
}
从上面可以看到,我们基本可以像定义类一样来定义枚举。我们还可以定义属性、构造方法等:
package com.mikan;
/**
* @author Mikan
* @date 2015-08-29 12:06
*/
public enum Operator {
ADD ("+") {
@Override
public int calculate(int a, int b){
return a + b;
}
},
SUBTRACT ("-") {
@Override
public int calculate(int a, int b){
return a - b;
}
},
MULTIPLY ("*") {
@Override
public int calculate(int a, int b){
return a * b;
}
},
DIVIDE ("/") {
@Override
public int calculate(int a, int b){
if (b == 0) {
throw new IllegalArgumentException("divisor must not be 0");
}
return a / b;
}
};
Operator (String operator) {
this.operator = operator;
}
private String operator;
public abstract int calculate(int a, int b);
public String getOperator(){
return operator;
}
}
实现原理分析
既然可以像使用普通的类一样使用枚举,编译器究竟为我们做了些什么事呢?要想知道这其中的秘密,最有效的途径就是查看生成的字节码。下面就来看看上面定义的枚举生成的字节码是怎么样的。
首先来看看反编译的基本信息:
localhost:mikan mikan$ javap Operator.class
Compiled from "Operator.java"