Java在JDK 5版本中从语言级别上引入了枚举支持。枚举是指一个经过排序的、被打包成一个单一实体的项列表。一个枚举的实例可以使用枚举项列表中任意单一项的值。可能的最简单的枚举是下面所显示的Colors枚举:
public enum Colors { red, green, blue }
它们给出了将一个任意项同另一个项相比较的能力,并且可以在一个已定义项列表中进行迭代。枚举(在Jave中简称为enum)是一个特定类型的类。所有枚举都是Java中的新类java.lang.Enum的隐式子类。此类不能手工进行子类定义。
在Java中内置枚举支持有许多好处。枚举是类型安全的,性能可与使用常量相媲美。枚举中的常量名称无需用枚举名称进行限定。客户端不需要建立对枚举中常量的了解,因此可以容易地对枚举进行修改,而无需修改客户端。如果常量从枚举中被删除了,那么客户端将会失败并且将会收到一个错误消息。枚举中的常量名称可以被打印,因此除了仅仅得到列表中项的序号外还可以获取更多信息。这也意味着常量可用作集合的名称,例如HashMap。
因为在Java中一个枚举就是一个类,它也可以有域和方法,并且实现接口。枚举在switch语句中可以一种直接的方式被使用,并且可以便于程序员相对简单地去理解和使用。
Java.lang.Enum类实现了Comparable和Serializable接口。在该类中已提供了比较枚举以及将它们序列化成为一个数据源的细节。不能将一个enum标记为abstract,除非每一个常量都有一个类主体,并且这些类主体覆盖了enum中的抽象方法。同时也要注意,枚举不能使用new进行实例化。编译器将会告知“enum types may not be instantiated.”(枚举类型不可以被实例化)。
Java引入了两个新集合:EnumSet和EnumMap,它们只是想在使用enum时优化集和映射的性能。枚举可以与当前已存在的集合类一起使用,或者在需要剪裁成枚举的优化活动时与新集合一起使用。
方法可声明在一个enum中。但是,对一个正在定义的构造方法来说会有所限制。构造函数不能链接超类构造方法,除非超类是另一个enum。enum中的每个常量都可以有一个类主体,但是因为这实际上是一个匿名类,因此不能定义一个构造函数。
也可以向枚举和单个enum常量添加属性。enum常量后面也可以跟有参数,这些参数被传递给在enum中定义的构造函数。
下面以一个例子来举例说明:
运行的结果为:package com; public enum WeekDay { Mon("Monday"), Tue("Tuesday"), Wed("Wednesday"), Thu("Thursday"), Fri( "Friday"), Sat("Saturday"), Sun("Sunday"); private final String day; private WeekDay(String day) { this.day = day; } /*enum常量后面也可以跟有参数,这些参数被传递给在enum中定义的构造函数。 如果把参数去掉 前面的 Mon("Monday")将不被认识,报错。*/ public static void printDay(int i){ switch(i){ case 1: System.out.println(WeekDay.Mon); break; case 2: System.out.println(WeekDay.Tue);break; case 3: System.out.println(WeekDay.Wed);break; case 4: System.out.println(WeekDay.Thu);break; case 5: System.out.println(WeekDay.Fri);break; case 6: System.out.println(WeekDay.Sat);break; case 7: System.out.println(WeekDay.Sun);break; default:System.out.println("wrong number!"); } } public String getDay() { return day; } public static WeekDay getEnumByValue(String in){ WeekDay wd = null; //wd=new WeekDay("Monday"); if(WeekDay.Mon.getDay().equals(in)){ wd = WeekDay.Mon; }else if(WeekDay.Tue.getDay().equals(in)){ wd = WeekDay.Tue; }else if(WeekDay.Wed.getDay().equals(in)){ wd = WeekDay.Wed; }else if(WeekDay.Thu.getDay().equals(in)){ wd = WeekDay.Thu; }else if(WeekDay.Fri.getDay().equals(in)){ wd = WeekDay.Fri; }else if(WeekDay.Sat.getDay().equals(in)){ wd = WeekDay.Sat; }else if(WeekDay.Sun.getDay().equals(in)){ wd = WeekDay.Sun; } return wd; } public static void main(String[] args) { /*WeekDay wd=new WeekDay("Monday"); //编译器将会告知“enum types may not be instantiated.”(枚举类型不可以被实例化)*/ WeekDay wd= getEnumByValue("Monday"); System.out.println(wd); printDay(2); } }
Mon
Tue
枚举原理:
Java Enum类型的语法结构尽管和java类的语法不一样,应该说差别比较大。但是经过编译器编译之后产生的是一个class文件。该class文件经过反编译可以看到实际上是生成了一个类,该类继承了java.lang.Enum<E>.
WeekDay经过反编译(javap WeekDay命令)之后得到的内容如下(去掉了汇编代码):
public final class WeekDay extends java.lang.Enum{
public static final WeekDay Mon; //WeekDay wd= getEnumByValue("Monday"); 所以这句话是正确的,因为Mon 本身就是WeekDay 类型。
public static final WeekDay Tue;
public static final WeekDay Wed;
public static final WeekDay Thu;
public static final WeekDay Fri;
public static final WeekDay Sat;
public static final WeekDay Sun;
static {};
public static void printDay(int);
public java.lang.String getDay();
public static WeekDay[] values();
public static WeekDay valueOf(java.lang.String);
}
所以实际上Enum类型就是以Java类来实现的,没有什么新的特点,只不过java编译器帮我们做了语法的解析和编译。