###概述

之前一直都不知道枚举类型是用来干什么的,今天敲了一下午代码之后,好像突然明白了点。。。

enum和class并无很大的差别,只是​非抽象​枚举类​不能派生子类​,且​枚举类的构造器都是默认以private修饰的,并且只能用private修饰

还有一点就是枚举类的的定义,下面的代码中第二行的四个枚举值就是​枚举类SeasonEnum的所有实例​,即​对象​,java规定他们必须在​枚举类定义的第一行列出

public enum SeasonEnum {
SPRING, SUMMER, FALL, WINTER;
}

枚举类型不能直接用new来生成对象

它的声明方式是这样的:

public static <T extends Enum<T>> T valueOf(Class<T>enum Type, String name)

它其实就是一个静态方法,用于返回​指定枚举类​中​指定名称的枚举值​。名称必须与在该枚举类声明枚举值时所用的标识符完全匹配,不允许使用额外的空白字符。

举个例子,如果上面的代码想要生成对象,可以这样写

SeasonEnum seasonEnum = SeasonEnum.valueOf(SeasonEnum.class, "FALL");

这样就得到了枚举值为FALL的枚举实例

其实还有一种写法,也可以达到上面的效果,同样也是得到一个指定枚举值的枚举实例

SeasonEnum seasonEnum = SeasonEnum.FALL

根据我目前的学习情况,我认为枚举有两种用途


  • 使用​匿名内部类​来使得自己的​实例以不同的方式实现​接口或者自己的​抽象方法
  • 建立映射,并且可以是​一对多的映射

下面我来当分别介绍这两点

###实现抽象方法

直接先看代码吧

public enum Operation {
PLUS {
public double eval(double x , double y) {
return x + y;
}
},
MINUS {
public double eval(double x , double y) {
return x - y;
}
},
TIMES {
public double eval(double x , double y) {
return x * y;
}
},
DIVIDE {
public double eval(double x , double y) {
return x / y;
}
};
//本枚举类的抽象方法
public abstract double eval(double x, double y);
public static void main(String[] args) {
System.out.println(Operation.PLUS.eval(3, 4));
System.out.println(Operation.MINUS.eval(5, 4));
System.out.println(Operation.TIMES.eval(5, 4));
System.out.println(Operation.DIVIDE.eval(5, 4));
}
}

上面的PLUS,MINUS,TIMES,DIVIDE其实就是Operation 枚举类的匿名内部类的对象

我们可以看一下它所生成的class文件

Java----枚举 enum_抽象方法

由class文件我们可以看出,它的确是产生了四个匿名内部类,这时候Operation的每一个​枚举值就不再是Operation的实例了​,而是​Operation匿名内部类的对象​,还有就是从这个例子中我们也能看出,只有抽象枚举类型才能派生子类,他在本例中​派生的子类就是那些匿名内部类​。注意:​匿名类一定是子类或者实现类​,因为他自己没有名字,所以一定需要依赖​父接口或者抽象类​。

有一个问题我也纠结了很长时间,因为原来接触的匿名内部类都是普通类的,枚举类的匿名内部类跟他们长的有点儿不一样,一开始我也懵了,不知道到底怎么回事儿了,后来给想通了,普通类的匿名内部类的形式无非就是

  • new 接口/父类名 {实现抽象方法}

大括号之前就是一个对象(引用)​,同样的,再去看上面例子中枚举类型的匿名内部类

  • PLUS {实现抽象方法}

其实已经很清楚了,这里的​PLUS就相当于​普通类匿名内部类声明中的那个new出来的​对象​,本来实现的就是本类中的抽象方法,因此​new 父类名​自然就产生了PLUS这个对象。

因为前面也提到过,PLUS、MINUS……这些就是枚举类的​枚举值​,​其实就是枚举类Operation的实例(对象)

我对Operation进行了反编译,得到了下面的结果,枚举值似乎就是Operation的对象

abstract class Operation extends java.lang.Enum<Operation> {
public static final Operation PLUS;
public static final Operation MINUS;
public static final Operation TIMES;
public static final Operation DIVIDE;
private static final Operation[] ENUM$VALUES;
static {};
private Operation(java.lang.String, int);
public abstract double eval(double, double);
public static Operation[] values();
public static Operation valueOf(java.lang.String);
Operation(java.lang.String, int, Operation);
}

这个就先说到这儿吧,我也有点儿纠结了。。。。

###建立映射

实现这个功能,靠的主要就是**getByValue()**方法,这个方法是自己在枚举类中定义的,可以吧value看成是一个key值,由它来映射到其他值,具体代码如下

public enum TypeEnum {  
VIDEO(1, "视频"), AUDIO(2, "音频"), TEXT(3, "文本"), IMAGE(4, "图像");
int value;
String name;
TypeEnum(int value, String name) {
this.value = value;
this.name = name;
}
public int getValue() {
return value;
}
public String getName() {
return name;
}

public TypeEnum getByValue(int value) {
for(TypeEnum typeEnum : TypeEnum.values()) {//values()方法会返回该枚举的所有值
if(typeEnum.value == value) {
return typeEnum;
}
}
//遍历所有的枚举值,找到属性值与value相等的并返回该枚举值
throw new IllegalArgumentException("No element matches " + value);
}
public static void main(String[] args) {
TypeEnum type = TypeEnum.VIDEO;
System.out.println(type.getByValue(4));
System.out.println(type.getByValue(4).getValue());
System.out.println(type.getByValue(4).getName());
}
}

在上面的代码中,通过枚举类TypeEnum的枚举值,我们建立了​从int到String的一个映射​,实现这个功能主要还是靠​枚举类的values()方法来遍历所有的枚举值​。

至于要建立什么样的映射以及要建立一对几的映射,都可以通过给枚举类​添加成员变量来实现​。

行了就说这么多吧,寝室快熄灯了都。。。。