Java枚举类型
java从JDK1.5开始支持枚举,也就是说,Java一开始是不支持枚举的,就像泛型一样,都是JDK1.5才加入的新特性。通常一个特性如果在一开始没有提供,在语言发展后期才添加,会遇到一个问题,就是向后兼容性的问题。像Java在1.5中引入的很多特性,为了向后兼容,编译器会帮我们写的源代码做很多事情,比如泛型为什么会擦除类型,为什么会生成桥接方法,foreach迭代,自动装箱/拆箱等,这有个术语叫“语法糖”,而编译器的特殊处理叫“解语法糖”。那么像枚举也是在JDK1.5中才引入的,又是怎么实现的呢?
Java在1.5中添加了java.lang.Enum抽象类,它是所有枚举类型基类。提供了一些基础属性和基础方法。同时,对把枚举用作Set和Map也提供了支持,即java.util.EnumSet和java.util.EnumMap。
一、枚举类型
枚举类型在java语言中是一种基本数据类型而不是构造数据类型
在我们日常的开发过程中,我们经常定义使用常量;在Effective Java建议用枚举来替换常量的使用,提高我们代码的质量
创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。
枚举类型符合通用模式 Class Enum>,而 E 表示枚举类型的名称。
枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。
在项目开发中,推荐使用枚举常量代替接口常量或类常量。
public enum Week { MON, TUE, WED, THU, FRI, SAT, SUN; }
这段代码实际上调用了7次 Enum(String name, int ordinal):
new Enum(“MON”,0);
new Enum(“TUE”,1);
new Enum(“WED”,2);
…….
用法一:常量
在JDK1.5 之前,我们定义常量都是: public static final…. 。现在好了,有了枚举,可以把相关的常量分组到一个枚举类型里,而且枚举提供了比常量更多的方法。
public enum Color { RED, GREEN, BLANK, YELLOW }
Color color = Color.Red; //color -> Red;
用法二:switch
JDK1.6之前的switch语句只支持int,char,enum类型,使用枚举,能让我们的代码可读性更强。
enum Signal { GREEN, YELLOW, RED } public class TrafficLight { Signal color = Signal.RED; public void change() { switch (color) { case RED: color = Signal.GREEN; break; case YELLOW: color = Signal.RED; break; case GREEN: color = Signal.YELLOW; break; } } }
用法三:向枚举中添加新方法
如果打算自定义自己的方法,那么必须在enum实例序列的最后添加一个分号。而且 Java 要求必须先定义 enum 实例。
public enum Color { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } // 普通方法 public static String getName(int index) { for (Color c : Color.values()) { if (c.getIndex() == index) { return c.name; } } return null; } // get set 方法 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } }
用法四:覆盖枚举的方法
下面给出一个toString()方法覆盖的例子。
public class Test { public enum Color { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } // 覆盖方法 @Override public String toString() { return this.index + "_" + this.name; } } public static void main(String[] args) { System.out.println(Color.RED.toString()); } }
用法五:实现接口
所有的枚举都继承自java.lang.Enum类。由于Java 不支持多继承,所以枚举对象不能再继承其他类。
public interface Behaviour { void print(); String getInfo(); } public enum Color implements Behaviour { RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4); // 成员变量 private String name; private int index; // 构造方法 private Color(String name, int index) { this.name = name; this.index = index; } // 接口方法 @Override public String getInfo() { return this.name; } // 接口方法 @Override public void print() { System.out.println(this.index + ":" + this.name); } }
用法六:使用接口组织枚举
public interface Food { enum Coffee implements Food { BLACK_COFFEE, DECAF_COFFEE, LATTE, CAPPUCCINO } enum Dessert implements Food { FRUIT, CAKE, GELATO } }
用法七:关于枚举集合的使用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。EnumSet保证集合中的元素不重复;EnumMap中的 key是enum类型,而value则可以是任意类型。
/** * * 演示枚举类型的遍历 */ private static void testTraversalEnum() { Light[] allLight = Light.values(); for (Light aLight : allLight) { System.out.println("当前灯name:" + aLight.name()); System.out.println("当前灯ordinal:" + aLight.ordinal()); System.out.println("当前灯:" + aLight); } } /** * * 演示EnumMap的使用,EnumMap跟HashMap的使用差不多,只不过key要是枚举类型 */ private static void testEnumMap() { // 1.演示定义EnumMap对象,EnumMap对象的构造函数需要参数传入,默认是key的类的类型 EnumMap<Light, String> currEnumMap = new EnumMap<Light, String>( Light.class); currEnumMap.put(Light.RED, "红灯"); currEnumMap.put(Light.GREEN, "绿灯"); currEnumMap.put(Light.YELLOW, "黄灯"); // 2.遍历对象 for (Light aLight : Light.values()) { System.out.println("[key=" + aLight.name() + ",value=" + currEnumMap.get(aLight) + "]"); } } /** * * 演示EnumSet如何使用,EnumSet是一个抽象类,获取一个类型的枚举类型内容<BR/> * * 可以使用allOf方法 */ private static void testEnumSet() { EnumSet<Light> currEnumSet = EnumSet.allOf(Light.class); for (Light aLightSetElement : currEnumSet) { System.out.println("当前EnumSet中数据为:" + aLightSetElement); } } }
更详细原理参见:
转载请注明来源:Java枚举类型