enum 的全称为 enumeration, 是 JDK 1.5 中引入的新特性,存放在 java.lang 包中。
下面是我在使用 enum 过程中的一些经验和总结,主要包括如下内容:
-
语法(定义)
-
遍历、switch 等常用操作
-
enum 对象的常用方法介绍
-
给 enum 自定义属性和方法
-
EnumSet,EnumMap 的应用
-
enum的比较
-
enum的name与ordinal的复写
语法(定义)
创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类(java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum<E extends Enum>,而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal) 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。
private enum SimpleEnum {
SPRING,
SUMMER,
AUTUMN,
WINTER;
}
这段代码实际上调用了4次 protected Enum(String name, int ordinal):
new Enum<SimpleEnum>("SPRING",0);
new Enum<SimpleEnum>("SUMMER",1);
new Enum<SimpleEnum>("AUTUMN",2);
new Enum<SimpleEnum>("WINTER",3);
遍历、switch 等常用操作
通过values获取所有实例
for (SimpleEnum simpleEnum : SimpleEnum.values()) {
System.out.println(simpleEnum + " ordinal " + simpleEnum.ordinal());
}
System.out.println("------------------");
SimpleEnum simpleEnum = SimpleEnum.SPRING;
switch (simpleEnum) {
case SPRING:
System.out.println("春天");
break;
case SUMMER:
System.out.println("夏天");
break;
case AUTUMN:
System.out.println("秋天");
break;
case WINTER:
System.out.println("冬天");
break;
default:
System.out.println("没有这个季节");
break;
}
enum 对象的常用方法介绍
-
int compareTo(E o)
比较此枚举与指定对象的顺序。
-
Class getDeclaringClass()
返回与此枚举常量的枚举类型相对应的 Class 对象。
-
String name()
返回此枚举常量的名称,在其枚举声明中对其进行声明。
-
int ordinal()
返回枚举常量的序数(它在枚举声明中的位置,其中初始常量序数为零)。
-
String toString()
返回枚举常量的名称,它包含在声明中。
-
static <T extends Enum> T valueOf(Class enumType, String name)
返回带指定名称的指定枚举类型的枚举常量。
下面是代码实例:
SimpleEnum simpleEnum = SimpleEnum.SPRING;
switch (simpleEnum.compareTo(SimpleEnum.SUMMER)) {
case -1:
System.out.println("春天在夏天前面");
break;
case 1:
System.out.println("春天在夏天后面");
break;
case 0:
System.out.println("春天和夏天一样");
break;
default:
System.out.println("没有这个季节");
break;
}
System.out.println(simpleEnum.toString()); //SPRING
System.out.println(simpleEnum.name()); //SPRING
System.out.println(simpleEnum.ordinal()); //0
给 enum 自定义属性和方法
private enum TYPE {
FIREWALL("firewall"), SECRET("secretMac");
// 自定义属性
private String typeName;
// 构造函数,不能定义为Public
TYPE(String typeName) {
this.typeName = typeName;
}
// 自定义方法
// 根据typeName获取实例
public static TYPE fromTypeName(String typeName) {
for (TYPE type : TYPE.values()) {
if (type.getTypeName().equals(typeName)) {
return type;
}
}
return null;
}
// 获取实例的typeName
public String getTypeName() {
return this.typeName;
}
// 重写方法
@Override
public String toString() {
// TODO Auto-generated method stub
return super.toString();
}
}
EnumSet,EnumMap 的应用
java.util.EnumSet和java.util.EnumMap是两个枚举集合。
EnumSet保证集合中的元素不重复;
EnumMap中的 key是enum类型,而value则可以是任意类型。
//EnumSet运用
EnumSet<SimpleEnum> enumSet = EnumSet.allOf(SimpleEnum.class);
for (SimpleEnum simpleEnum : enumSet) {
System.out.println(simpleEnum.name());
}
//EnumMap运用
EnumMap<SimpleEnum, String> enumMap = new EnumMap<>(SimpleEnum.class);
enumMap.put(SimpleEnum.SPRING, "春天");
enumMap.put(SimpleEnum.SUMMER, "夏天");
System.out.println("map");
for (SimpleEnum simpleEnum : enumMap.keySet()) {
System.out.println(simpleEnum.name());
}
enum的比较
比较我们都知道有==和equals,那么针对enum我们使用什么呢?
SimpleEnum simpleEnum1 = SimpleEnum.SPRING;
SimpleEnum simpleEnum2 = SimpleEnum.SPRING;
SimpleEnum simpleEnum3 = SimpleEnum.SUMMER;
System.out.println(simpleEnum1 == simpleEnum2); //true
System.out.println(simpleEnum1.equals(simpleEnum2)); //true
System.out.println(simpleEnum1 == simpleEnum3); //false
System.out.println(simpleEnum1.equals(simpleEnum3)); //false
原因如下:
/**
* Returns true if the specified object is equal to this
* enum constant.
*
* @param other the object to be compared for equality with this object.
* @return true if the specified object is equal to this
* enum constant.
*/
public final boolean equals(Object other) {
return this==other;
}
这里重写的equals方法比较的就是==,所以我们也可以直接用==判断
enum的name与ordinal的复写
说到这个自带两个属性,很多人第一反应就是不能重写,因为没有方法让你写,下面直接给出代码
public void setNameAndOrdinal(String typeName, int ordinal) {
TYPE type = fromTypeName(typeName);
try {
Field field = getClass().getSuperclass().getDeclaredField("name");
field.setAccessible(true);
field.set(this, typeName);
field.setAccessible(false);
Field field1 = getClass().getSuperclass().getDeclaredField("ordinal");
field1.setAccessible(true);
field1.set(this, ordinal);
field1.setAccessible(false);
} catch (Exception e) {
// TODO: handle exception
}
}
我们可以通过操作反射,来获取父类的私有属性,从而进行一个赋值