Java的Enum类型介绍 (格式待整理)

Java的Enum类型介绍


JDK从1.5版本开始支持Enum类型。Enum类型可以将一组类似的值包含在一种类型中。如{MON, TUE, WEN,THU, FRI}。这一点类似于常量类型。但Enum类型提供了相比与常量类型提供了更多的可操作性。

一.与常量类型定义的区别 

常用的常量定义方法是使用static final修饰符,这种方法存在一些问题,使用Enum类定义常量可以避免这些问题的产生。

1.static final 类型常量定义

使用static final方法定义常量是常用的方法。在使用这种方法定义常量时定义方便,但存在一些问题。
类型不安全。两个不相关的常量可以进行比较和运算。
必须通过类访问。由于常量是类的成员变量,其他类需要访问时必须通过类来访问。
修改时麻烦。由于static final型的常量属于编译时常量。即每次编译过程结束后,在.class文件中写入的是常量的值,如下面的示例中,所有引用RED的地方被替换为0.在.class文件中不会有RED出现。这样的不方便之处在于每次修改常量的值时,所有引用该常量的文件都需要重新编译。
代码示例:
public class TrifficLight
{
public static final int RED = 0;
public static final int GREEN = 1;
public static final int YELLOW = 2;
}
类型无指义性。由于属于编译时常量,在运行期调试时,日志中出现的只是数字,难以理解。

2.Enum型定义常量

Java中的Enum类型的声明方式如下:
public enum TrifficLight {RED, GREEN, YELLOW};
这一组枚举类型中的值与其他定义的枚举类型中的值是不可以比较和计算的,否则将产生编译错误。这提供了类型安全性。并且因为Enum类型不是编译时常量,在修改Enum时,只需要编译修改的文件,不需要再编译引用它的文件。
与C/C++中的Enum类型不同的是Java中允许在Enum类型的定义中添加任意的方法和域,并实现任意的接口。除了Enum无法继承其他的类以外(Java中是单继承,Enum已经继承了java.lang.enum类)和一个普通的类的功能一样。
下面是在Enum中添加方法和域的示例:
public enum TrifficLight
{
RED(1),GREEN(2),YELLOW(3);
private int index;
private TrifficLight (int index)
{
this.index = index;
}
public int getIndex()
{
return index;
}
}
通过这种添加域与方法的方式,引用该Enum类型时,可以通过getIndex()方法访问在定义时赋予的值。即在其他类中,可以通过TrifficLight.RED.getIndex()得到RED初始化的值1.对于初始化的值得类型,可以是任何基本类型,也可以是自定义的类。Enum类型具有一些自带的方法,如name()——获取Enum类型定义的名称,如RED;ordinal()——获取Enum类型的序号;toString()——可覆盖,默认范围Enum类型定义的名称。这样Enum类型即可实现灵活的常量定义的功能,并使常量具有一定的指义性。

二.Enum复杂操作

Enum类型除了进行普通的常量定义外还具有其他的功能。如使用switch语句、定义复杂逻辑、使用EnumSet、EnumMap管理等功能。

使用switch语句

Switch语句支持Enum类型,示例如下:
TrifficLight light = TrifficLight.RED;
switch(light)
{
case RED : ...;break;
case GREEN : ...;break;
case YELLOW : ...;break;
default : ...;break;
}

2.遍历Enum类型

Enum自带的values()方法可以用来遍历Enum中的数据。示例如下:
for (TrifficLight light : TrifficLight.values())
{
System.out.println(light.name());
}
输出结果为:
RED
GREEN
YELLOW

使用自带工具类

Enum类具有两个工具类,EnumSet和EnumMap。
EnumSet类。EnumSet类是针对Enum类的Set接口的实现。同一个EnumSet中装入的必须是同一类型的Enum.EnumSet具有若干遍历或取子集的方法,现举其中一个示例如下:
for(TrifficLigth light : EnumSet.range(TrifficLight.RED, TrifficLight.GREEN))
{
System.out.println(light.name());
}
输出为:
RED
GREEN
其中range()方法用于在一个范围内对Enum进行迭代,另外of()方法可以用于取Enum的子集,allOf()方法可以去Enum的全集。
(2)EnumMap类。EnumMap类是针对Enum类的Map接口的实现。EnumMap中的key是Enum类型。示例如下:
private Map<TrifficLight, String> mapTest = new EnumMap<TrifficLight, String>
(TrifficLight.class);
mapTest.put(TrifficLight.RED, new String(“red”));
System.out.println(mapTest.get(TrifficLight.RED));

使用接口组织Enum

Enum类不可以继承其他类,但可以实现接口,通过接口可以实现Enum类的扩展。示例如下:
public interface Fruit{}
public enum Apple implements Fruit{FUJI,PIPPIN};
public enum Orange implements Fruit{NAVEL, TEMPLE};
则所有的Enum类型都是一种Fruit。定义方法如下:
private static <T extends Enum<T> & Fruit> void taste(Class<T> fruitSet)
{
for(Fruit fruit : fruitSet.getEnumConstants())
{
System.out.println(fruit);
}
}
调用taste(Apple.class);输出:
FUJI
PIPPIN
调用taste(Orange.class);输出:
NAVEL
TEMPLE

对每个Enum对象自定义方法

由于每个Enum的对象均为一个类,则在其中可以自定义方法。示例如下:
enum Apple
{
FUJI {public void taste(){System.out.println("it's sweet");}},
PIPPIN {public void taste(){System.out.println("it's sweet,too");}};
abstract void taste();
}
调用:
for(Apple apple : Apple.values())
{
apple.taste();
}
输出:
it's sweet
it's sweet,too
利用这种自定义特性,可以使用Enum类型实现责任链模式,也可以用来实现状态机。

三.使用Enum注意事项

使用Enum时需要注意几点:
构造函数。构造函数为private型,不能使public或protected。所有枚举对象不能在外部声明,Enum只在引用它的第一次对所有的对象进行初始化一次。
符号。定义Enum类型时,如果是简单类型,则最后一个枚举值后不用跟任何一个符号,如果有定制方法,则必须跟一个分号“;”。
判断相等。由于Enum的类型时通过运行期构造出对象来表示的,所以在集群环境下,不同虚拟机中构造出的枚举对象通过“==”来判断相等返回为false,由于二者不是同一个对象实例。在比较时需要注意。

posted @ 2013-10-22 15:32  Moonc.  阅读(803)  评论(0编辑  收藏  举报