###概述
之前一直都不知道枚举类型是用来干什么的,今天敲了一下午代码之后,好像突然明白了点。。。
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()方法来遍历所有的枚举值

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

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