enum (enumeration)
, 是 JDK 1.5
中引入的新特性,在 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);
... ...
- 枚举类是特殊的
class
,有构造器、方法和数据域,被final
修饰,不可被继承; - 枚举值
MON, TUE...
都是Week
类型的静态常量(public static final 修饰
),故通常全部大写。
// 获取实例
Week w = Week.MON;
使用
一. 自定义方法、覆盖枚举的方法
自定义方法时必须在enum
实例序列最后添加分号。同时Java
要求必须先定义 enum
实例.
enum Week {
MON(2016, 12, 12), TUE(2016, 12, 13), WED(2016, 12, 14), THU(2016, 12, 15),
FRI(2016, 12, 16), SUN(2016, 12, 17), SUN(2016, 12, 18);
//自定义数据域 (get、set 封装)
private int year;
private int mouth;
private int day;
// 构造枚举值
private Week (int year, int mouth, int day){
this.year = year;
this.mouth = mouth;
this.day = day;
}
// 自定义方法
public String getDate(int day) {
for (Week w : Week.values()) { // 遍历
if (w.getDay() == day) {
return toString();
}
}
return null;
}
//覆盖方法
@Override
public String toString() {
return w.year + "年" + w.mouth + "月" + w.day + "日" ;
}
}
注意:
- 构造器只在构造枚举值时被调用;
- 构造器只能私有
private
,不允许public
修饰。保证了外部代码无法构造新枚举类的实例,因为枚举值是public static final
的常量。 但枚举类的方法和数据域允许外部访问。
// 错误写法
Week week = new Week(2017, 1, 1);
// 正确写法
Week week = Week.MON;
System.out.println(week.getDate());
二. switch 操作
public void change() {
Week week = Week.WED;
switch (week) {
case MON:
week = Week.MON;
break;
case TUE:
week = Week.TUE;
break;
case WED:
week = Week.WED;
break;
……
}
三. 实现接口
枚举继承java.lang.Enum
类。Java
不支持多继承,所以枚举对象不能继承其它类。
public interface Behaviour {
void print();
String getDayOfMouth();
}
enum Week {
MON(2016, 12, 12), TUE(2016, 12, 13), WED(2016, 12, 14), THU(2016, 12, 15),
FRI(2016, 12, 16), SUN(2016, 12, 17), SUN(2016, 12, 18);
// 成员变量 (get、set 封装)
private int year;
private int mouth;
private int day;
// 构造方法
private Week (int year, int mouth, int day){
this.year = year;
this.mouth = mouth;
this.day = day;
}
// 接口方法
@Override
public String getDayOfMouth(int day) {
return this.day;
}
// 接口方法
@Override
public String print() {
System.out.println(w.year + "年" + w.mouth + "月" + w.day + "日");
}
四. 接口组织枚举
public interface Animal {
enum Water implements Animal {
SHARK, DOLPHIN, WHALE
}
enum Land implements Animal {
DOG, CAT, PIG, WOLF, TIGER
}
}
五. 方法
继承于Enum
的方法。
-
int compareTo(E o)
比较此枚举与指定对象的顺序(Enum
实现了java.lang.Comparable
接口)。返回两个枚举值的顺序之差。枚举必须属于同一个枚举类,否则抛出ClassCastException()
异常。
// MON, TUE, WED, THU, FRI, SUN, SUN
Week.MON.compareTo(Week.WED); // 结果 -2
Week.WED.compareTo(Week.MON); // 结果 2
-
final boolean equals(Object other)
比较两个枚举类对象的引用。 -
Class
getDeclaringClass()
返回与此枚举常量的枚举类型相对应的Class
对象。
Week week = Week.MON;
System.out.println(week.getDeclaringClass().getName());
// 输出结果:com.enumtest.test.Week;
-
String name()
返回此枚举常量的名称,在其枚举声明中对其进行声明。 -
int ordinal()
返回枚举常量在枚举类中的次序(初始常量序数为 0)。
Week.MON.ordinal(); // 结果 0
Week.WED.ordinal(); // 结果 2
-
String toString()
返回枚举常量的名称。
Week w = Week.MON;
System.out.println(w);//返回结果: MON
-
static
> T valueOf(Class enumType, String name)
返回带指定名称的指定枚举类型的枚举常量,与toString()
方法相对应。
Week.valueOf("MON"); // 结果 Week.MON
-
values()
静态方法,返回一个包含全部枚举值的数组。
Week weeks = Week.values();
for(Week w:weeks){
System.out.print(w + ",");
}
//返回结果:MON, TUE, WED, THU, FRI, SUN, SUN
五. 枚举集合
java.util.EnumSet
:保证集合中的元素不重复。
java.util.EnumMap
:key
是enum
类型,value
可以是任意类型。
// EnumSet的使用
EnumSet weekSet = EnumSet.allOf(Week.class);
for (Week w : weekSet) {
System.out.println(w);
}
// EnumMap的使用
EnumMap weekMap = new EnumMap(Week.class);
weekMap.put(Week.MON, "星期一");
weekMap.put(Week.TUE, "星期二");
// ... ...
for (Iterator> iter = weekMap.entrySet().iterator();
iter.hasNext();) {
Entry entry = iter.next();
System.out.println(entry.getKey().name() + ":" + entry.getValue());
}
原理
enum
的语法结构和 class
的不同,但编译器编译之后生成一个class
文件。经反编译,可知该class
文件生成了一个继承java.lang.Enum
的类。
public class com.dev.test.Week extends java.lang.Enum{
public static final com.dev.test.Week MON;
public static final com.dev.test.Week TUE;
public static final com.dev.test.Week WED;
public static final com.dev.test.Week THU;
public static final com.dev.test.Week FRI;
public static final com.dev.test.Week SAT;
public static final com.dev.test.Week SUN;
static {};
public int getValue();
public boolean isRest();
public static com.dev.test.Week[] values();
public static com.dev.test.Week valueOf(java.lang.String);
com.dev.test.Week(java.lang.String, int, int, com.dev.test.Week);
}