Java的枚举类,一般的常用方式是使用枚举代表各类选项,既限定了接受值的范围,又便于记忆。如使用枚举定义星期几、性别等等。
看一个最简单的枚举:
public enum SimpleEnum {
MONDAY, TUESDAY;
}
在使用这个枚举时,我们可以使用以下的方法:
SimpleEnum.TUESDAY.name();
SimpleEnum.MONDAY.ordinal();
SimpleEnum.values();
SimpleEnum.valueOf("WEDNESDAY");
反编译看一下:
Compiled from "SimpleEnum.java"
// 说明enum定义的枚举,是java.lang.Enum类的子类
public final class jdk.test.Enum.SimpleEnum extends java.lang.Enum<jdk.test.Enum.SimpleEnum> {
private SimpleEnum(String s, int i)
{
super(s, i);
}
public static SimpleEnum[] values()
{
SimpleEnum asimpleenum[];
int i;
SimpleEnum asimpleenum1[];
System.arraycopy(asimpleenum = ENUM$VALUES, 0, asimpleenum1 = new SimpleEnum[i = asimpleenum.length], 0, i);
return asimpleenum1;
}
public static SimpleEnum valueOf(String s)
{
return (SimpleEnum)Enum.valueOf(jdk/test/Enum/SimpleEnum, s);
}
public static final SimpleEnum MONDAY;
public static final SimpleEnum TUESDAY;
private static final SimpleEnum ENUM$VALUES[];
static
{
MONDAY = new SimpleEnum("MONDAY", 0);
TUESDAY = new SimpleEnum("TUESDAY", 1);
ENUM$VALUES = (new SimpleEnum[] {
MONDAY, TUESDAY
});
}
}
再看一下java.lang.Enum类的源码:
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
// Enum的私有属性,name,结合字节码,name属性的值就是实例对象的变量名的String
private final String name;
public final String name() {
return name;
}
// 序号值,从0开始 ,static初始化块中操作
private final int ordinal;
public final int ordinal() {
return ordinal;
}
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
public String toString() {
return name;
}
public final boolean equals(Object other) {
return this==other;
}
public final int hashCode() {
return super.hashCode();
}
/**
* Throws CloneNotSupportedException. This guarantees that enums
* are never cloned, which is necessary to preserve their "singleton"
* status.
*
* @return (never returns)
*/
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
/**
* enum classes cannot have finalize methods.
*/
protected final void finalize() { }
/**
* prevent default deserialization
*/
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
throw new InvalidObjectException("can't deserialize enum");
}
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("can't deserialize enum");
}
}
实际上看来,enum只是类的一种特殊形式,它实际上和普通的类没有什么区别,只是JVM将他区别对待,让他在定义时可以以特殊的形式来进行,其他事情交给了JVM。
而且,有趣的是,Enum这个抽象类,我们是无法通过继承它来创造自己的实现类的。
话说回来,既然枚举和正常类没有什么区别,那是不是可以像普通类定义构造器,各种方法,私有属性呢?
事实证明,当然是可以的。
- 可以实现接口
- 可以定义属性和方法
- 不可以显式的调用其构造器(因为是private)
- 不可以继承类(因为暗含父类了)
- 可以定义抽象方法,且定义抽象方法时,enum反编译是抽象类。
例:
public interface IEnum {
void test();
}
public enum MyEnum implements IEnum {
ONE(1) {
@Override
void what() {
// TODO Auto-generated method stub
}
},
TWO(2) {
@Override
void what() {
// TODO Auto-generated method stub
}
};
private int num;
abstract void what();
MyEnum(int num) {
this.setNum(num);
}
public int getNum() {
return num;
}
public void setNum(int num) {
this.num = num;
}
@Override
public void test() {
System.out.println("test");
}
}
// decomplie
public abstract class MyEnum extends Enum
implements IEnum
{
private MyEnum(String s, int i)
{
super(s, i);
FIVE.num = 5;
}
abstract void what();
private MyEnum(String s, int i, int num)
{
super(s, i);
setNum(num);
FIVE.num = 5;
}
public MyEnum getFive()
{
return FIVE;
}
public int getNum()
{
return num;
}
public void setNum(int num)
{
this.num = num;
}
public void test()
{
System.out.println("test");
}
public static MyEnum[] values()
{
MyEnum amyenum[];
int i;
MyEnum amyenum1[];
System.arraycopy(amyenum = ENUM$VALUES, 0, amyenum1 = new MyEnum[i = amyenum.length], 0, i);
return amyenum1;
}
public static MyEnum valueOf(String s)
{
return (MyEnum)Enum.valueOf(jdk/test/Enum/MyEnum, s);
}
MyEnum(String s, int i, int j, MyEnum myenum)
{
this(s, i, j);
}
public static final MyEnum ONE;
public static final MyEnum TWO;
private int num;
private MyEnum FIVE;
private static final MyEnum ENUM$VALUES[];
static
{
ONE = new MyEnum("ONE", 0, 1) {
void what()
{
}
}
;
TWO = new MyEnum("TWO", 1, 2) {
void what()
{
}
}
;
ENUM$VALUES = (new MyEnum[] {
ONE, TWO
});
}
}
class MyEnum$1 extends MyEnum
{
void what()
{
}
MyEnum$1(String s, int i, int $anonymous0)
{
super(s, i, $anonymous0, null);
}
}
class MyEnum$2 extends MyEnum
{
void what()
{
}
MyEnum$2(String s, int i, int $anonymous0)
{
super(s, i, $anonymous0, null);
}
}