枚举概述
枚举类型是Java 5中新增特性的一部分,它是一种特殊的数据类型,之所以特殊是因为它既是一种类却又比普通类多了些特殊的约束,但是这些约束的存在也造就了枚举类型的简洁性、安全性以及便捷性。
枚举类型的定义
没有枚举类型时定义常量常见的方式:
public class DayDemo {
public static final int MONDAY =1;
public static final int TUESDAY=2;
public static final int WEDNESDAY=3;
public static final int THURSDAY=4;
public static final int FRIDAY=5;
public static final int SATURDAY=6;
public static final int SUNDAY=7;
}
上述的常量定义常量的方式称为int枚举模式,这样的定义方式并没有什么错,但它存在许多不足,如在类型安全和使用方便性上并没有多少好处,如果存在定义int值相同的变量,混淆的几率还是很大的,编译器也不会提出任何警告,因此这种方式在枚举出现后并不提倡,现在我们利用枚举类型来重新定义上述的常量。
// 枚举类型使用关键字enum定义
enum Day {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
枚举类型的使用
public class EnumDemo {
public static void main(String[] args){
//直接引用
Day day =Day.MONDAY;
}
}
//定义枚举类型
enum Day {
MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY, SUNDAY
}
枚举实现原理
实际上在使用关键字enum创建枚举类型并编译后,编译器会为我们生成一个继承了java.lang.Enum的类,也就是说通过关键字enum创建枚举类型在编译后事实上也是一个类类型而且该类继承自java.lang.Enum类。下面我们编译前面定义EnumDemo.java并查看生成的class文件来验证这个结论:
//反编译Day.class
final class Day extends Enum
{
//编译器添加的静态方法values()
public static Day[] values()
{
return (Day[])$VALUES.clone();
}
//编译器添加的静态方法valueOf(),注意间接调用了Enum也类的valueOf方法
public static Day valueOf(String s)
{
return (Day)Enum.valueOf(com/test/enumdemo/Day, s);
}
private Day(String s, int i)
{
super(s, i);
}
public static final Day MONDAY;
public static final Day TUESDAY;
public static final Day WEDNESDAY;
public static final Day THURSDAY;
public static final Day FRIDAY;
public static final Day SATURDAY;
public static final Day SUNDAY;
private static final Day $VALUES[];
static
{
//实例化枚举实例
MONDAY = new Day("MONDAY", 0);
TUESDAY = new Day("TUESDAY", 1);
WEDNESDAY = new Day("WEDNESDAY", 2);
THURSDAY = new Day("THURSDAY", 3);
FRIDAY = new Day("FRIDAY", 4);
SATURDAY = new Day("SATURDAY", 5);
SUNDAY = new Day("SUNDAY", 6);
$VALUES = (new Day[] {
MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
});
}
}
枚举的常见方法
Enum抽象类(是所有枚举类的父类)常见方法。
返回类型 | 方法名称 | 方法说明 |
int | compareTo(E o) | 比较枚举的大小(根据在枚举类中声明的位置),返回当前对象与对象o位置的差值 |
boolean | equals(Object other) | 当指定对象等于此枚举常量时,返回 true。 |
Class<?> | getDeclaringClass() | 返回与此枚举常量的枚举类型相对应的 Class 对象 |
String | name() | 返回此枚举常量的名称,在其枚举声明中对其进行声明 |
int | ordinal() | 返回枚举常量的序数(在枚举类中声明的位置,从0开始) |
String | toString() | 返回枚举常量的名称,它包含在声明中 |
static<T exitnds Enum< T >> T | static valueOf(Class enumType, String name) | 返回带指定名称的指定枚举类型的枚举常量。 |
public class Test {
public static void main(String[] args) {
// 按照加入顺序,north=0、east=1、south=2、west=3
Direction north = Direction.NORTH;
Direction east = Direction.EAST;
Direction south = Direction.SOUTH;
Direction west = Direction.WEST;
// values();
Direction[] directions = Direction.values(); // [NORTH,EAST,SOUTH,WEST]
for(Direction direction: directions) {
System.out.println(direction);
}
// compareTo
System.out.println(north.compareTo(west)); // 0-3=-3
// equals
Direction north2 = Direction.NORTH;
System.out.println(north2.equals(north)); // true
System.out.println(north2.equals(east)); // false
// 获取该枚举对象的Class对象引用
System.out.println(north.getDeclaringClass()); // class com.test.Direction
// name()
System.out.println(north.name()); // NORTH
// toString()
System.out.println(north.toString()); // NORTH
// valueof()
Direction north3 = Direction.valueOf(Direction.class, "NORTH");
System.out.println(north3); // NORTH
}
}
enum Direction{
NORTH,
EAST,
SOUTH,
WEST
}
编译器生成的Values()与ValueOf()
- values():获取一个枚举类中所有的枚举,并以数组形式返回。
- valueOf(String name):根据名称获取枚举变量。
public class Test {
public static void main(String[] args) {
// values() 返回枚举类Direction内的所有枚举构成的数组
Direction[] directions = Direction.values();
for(Direction direction : directions) {
System.out.println(direction);
}
// 根据枚举名称返回对应枚举对象
Direction north = Direction.valueOf("NORTH");
System.out.println(north);
}
}
enum Direction{
NORTH,
EAST,
SOUTH,
WEST
}
枚举与Class对象
当枚举实例向上转型为Enum类型后,values()方法将会失效,也就无法一次性获取所有枚举实例变量,但是由于Class对象的存在,即使不使用values()方法,还是有可能一次获取到所有枚举实例变量的,在Class对象中存在如下方法:
返回类型 | 方法名称 | 方法说明 |
T[ ] | getEnumConstants() | 返回该枚举类型的所有元素,如果Class对象不是枚举类型,则返回null。 |
boolean | isEnum() | 当且仅当该类声明为源代码中的枚举时返回 true |
public class Test {
public static void main(String[] args) {
//正常使用
Direction[] ds=Direction.values();
//向上转型Enum
Enum e = Direction.NORTH;
//无法调用,没有此方法
//e.values();
//获取class对象引用
Class<?> clasz = e.getDeclaringClass();
if(clasz.isEnum()) {
Direction[] dsz = (Direction[]) clasz.getEnumConstants();
System.out.println("dsz:"+Arrays.toString(dsz));
}
}
}
enum Direction{
NORTH,
EAST,
SOUTH,
WEST
}