用的不多,但用的时候仅仅简单的使用,不太明白原理,今天就系统的学一下枚举。参考:java编程思想。
Update:
- 枚举可以当做数据字典来存储,通常只要一个字段即instance本身,toString()或者name()打印的string。
- 枚举的数据都是一个实例对象,比如 enum Test{A}中A就是一个对象,A的toString和name()的结果是“A”。而如果一个字符串为"A",可以转为对应的枚举实例:Test.valueOf("A")
1.简单创建
枚举就是一个固定的集合,内容是声明的类。
创建enum的时候,里面的元素就是类,默认创建了toString(),odinal()方法以及value字段。其中odinal是声明的顺序(从0开始),value就是声明的名字。简单的使用的话,这样就可以了,配合switch即可。
2.深入了解
2.1基本特性
创建enum时,编译器会为你生成一个相关的类,这个类继承自java.lang.Enum。下面实例:
ordinal()方法返回一个int值,这个每个enum实例在声明时的次序,从0开始。可以使用==比较enum实例,编译器自动为你提供了equals()和hashCode()方法。Enum类实现了Comparable接口和Serializable接口。
2.1.1静态导入
在使用enum的实例的时候发现人家不是EnumClass.INSTANCE,即不是通过类名调用的,而是直接调用,看了下。原来是在包下静态导入了。即:
import static package.EnumClass.*。
究竟显示的修饰enum实例还是静态导入要看代码的复杂度,看看静态导入是不是会让代码难以理解。
2.2可以在enum中添加自己的方法
enum可以添加方法和构造器。
通常,将enum的构造方法声明private,而实际上对于它的可访问性来说没有什么变化,因为即使不是private也只能在enum内部使用创建enum实例。一旦enum定义结束,编译器就不允许我们再使用其构造器来创建任何实例了。另外,必须优先声明实例,然后声明方法或属性,否则编译报错。
2.3探究values()
经过一下检测,values是编译器添加到你创建的enum类的,而Enum类本身中并没有values方法。我们可以通过Class对象获取所有的enum实例。
2.4通过实现接口而不是继承他类来扩展
应为所有enum类都继承java.lang.Enum类。由于java不支持多继承,所以你的enum不能再继承其他类。但是可以实现多个接口。
2.5随机选取
2.6使用接口组织枚举
无法从enum继承子类有时很令人沮丧。这种需求有时源自我们希望扩展原enum中的元素,有时我们希望使用子类将一个enum中的元素进行分组。
在一个接口内部创建实现该接口的枚举,以此将元素进行分组,可以达到将枚举元素分类的目的。举例来说,假设想用enum表示不同的食物,同时还希望每个enum元素仍然保持Food类型。可以这样:
如果enum类型实现了Food接口,那么我们就可以将其实例向上转型为Food,所以上例中的所有东西都是Food。
然而当你需要与一大堆类型打交道时,接口就不如enum好用。例如,你想创建一个枚举的枚举。那么可以创建一个新的enum,然后用其实例包装Food中的每一个enum类。
在上面的程序中,每个Course实例都将其对应的Class对象作为构造器的参数。通过getEnumConstants方法,可以从该Class对象中取得某个Food子类的所有enum实例。因此,我们通过随机可以生成一份菜单:
在这个例子中,我们通过遍历每个Course实例来获得枚举的枚举的值。此外,还可以更简洁:将一个enum嵌套在另一个enum内。
Security接口的作用是将其所包含的enum组成一个公共类型,这一点是必要的。然后SecurityCategory才能将Security中的enum作为其构造器的参数作用,以起到组织的效果。
如果我们将这种方式应用于Food实例,结果是这样:
这仅仅是重新组织了下代码,不过多数情况下,这种方式使你的代码具有更清晰的结构。
2.7使用EnumSet代替标识
java se5引入EnumSet,是为了通过enum创建一种替代品,以替代传统的基于int的“标志位”。这种标识可以用来表示某种“开/关”信息。
下面enum表示在一座大楼中,警报传感器的安防位置:
2.8 使用EnumMap
EnumMap是一种特殊的Map,它要求其中的key必须来自一个enum。由于enum本身的限制,所以EnumMap在内部可由数组实现。因此EnumMap速度很快。
下面演示了命令设计模式的用法。一般来说,命令模式首先需要一个只有单一方法的接口,然后从该接口实现具有各自不同的行为的多个子类。接下来,程序员就可以构造命令对象,并在需要的时候使用它们。
与EnumSet一样,enum实例定义时的次序决定了其在EnumMap中的顺序。enum的每个实例作为一个键总是存在的,如果你没有为这个键调用put来存入相应的值,则对应的值为null。
与常量相关的方法相比,EnumMap有一个有点,允许程序员改变值对象,而常量相关的方法在编译器就被固定了。
2.9常量相关方法
java的enum有个特性:允许程序员为enum实例编写方法,从而为每个enum实例赋予各自不同的行为。要实现常量相关的方法,你需要为enum定义一个或者多个abstract方法,然后为每个enum实例实现该抽象方法。如下:
通过相应的enum实例,我们可以调用其上的方法。这通常也成为表驱动的代码(table-driven code),请注意它与前面提到的命令模式的相似之处。
在面向对象的程序设计中,不同的行为与不同的类关联。而通过常量相关的方法,每个enum实例可以具备自己独特的行为,这似乎说明每个enum实例就是一个特殊的类。我们并不能真的将enum实例当做一个类来使用。
本文转自Ryan.Miao博客园博客,原文链接:http://www.cnblogs.com/woshimrf/p/5337953.html,如需转载请自行联系原作者