enum 的特征
public enum ColorEnum {
RED("红色"),
BLUE("蓝色"),
GREEN("绿色"),
;
private String description;
private static Random random = new Random(4l);
ColorEnum(String description){
this.description = description;
}
public String getDescription() {
return description;
}
@Override
public String toString(){
return "enum:" + this.name();
}
public static ColorEnum next(){
return values()[random.nextInt(values().length)];
}
public static void main(String[] args){
// 1.values()
for(ColorEnum colorEnum : ColorEnum.values()) {
// 2.name() 与 toString()
System.out.print(colorEnum.name() + " ");
System.out.print(colorEnum + " ");
System.out.print(colorEnum.getDescription() + " ");
// 3.ordinal()
System.out.println(colorEnum.ordinal());
}
ColorEnum colorEnum = ColorEnum.next();
// 4.valueOf()
ColorEnum colorEnum1 = ColorEnum.valueOf(colorEnum.name());
// 5.单例,equals 和 == 结果相同
System.out.println(colorEnum == colorEnum1);
System.out.println(colorEnum.equals(colorEnum1));
// 6.getDeclaringClass()
System.out.println(colorEnum.getDeclaringClass());
// 7.compareTo() 声明顺序比较
System.out.println(colorEnum.compareTo(RED));
System.out.println(colorEnum.compareTo(BLUE));
System.out.println(colorEnum.compareTo(GREEN));
// 8.getEnumConstants()
ColorEnum[] values = ColorEnum.class.getEnumConstants();
}
}
- name() 一定返回枚举定义时的名称,toString 默认情况下与 name() 相同,但是在子类中 toString 可以覆盖,而 name() 是 final 的。
- 枚举的实现是单例的,但是还是使用 equals 养成良好习惯。
神奇的 enum
将上一个例子编译后的 .class 文件进行反编译后,会看到一些有趣的问题:
Compiled from "ColorEnum.java"
public final class lirui.ColorEnum extends java.lang.Enum<lirui.ColorEnum> {
public static final lirui.ColorEnum RED;
public static final lirui.ColorEnum BLUE;
public static final lirui.ColorEnum GREEN;
public static lirui.ColorEnum[] values();
public static lirui.ColorEnum valueOf(java.lang.String);
public java.lang.String getDescription();
public static lirui.ColorEnum next();
public java.lang.String toString();
public static void main(java.lang.String[]);
static {};
}
- 编译器为类声明添加了 final,并且继承了 Enum 类,所以编写枚举类时不能在继承其他类,但是可以实现接口。
- 编译器添加了 static final 的枚举对象,这也是我们平时可以使用 ColorEnum.RED 获取枚举实例的原因。所以枚举实现是单例的。
- 编译器添加了 values(),valueOf() 这两个方法,而对于他的父类 Enum 也有一个valueOf(),不过两者参数不同,并不是同一个方法。
- 将 ColorEnum 向上转型为 Enum 时,values() 方法将失效,但是可以使用 Class 上的 getEnumConstants() 获取所有 enum 实例。
enum 的多态
- Java 允许为 enum 实例编写方法,可以为 enum 定义一个或多个 abstract 方法,然后为每个 enum 实例实现该抽象方法。
public enum ColorEnum{
RED("红色"){
public String getName(){
return "红色";
}
},
BLUE("蓝色"){
public String getName(){
return "蓝色";
}
},
GREEN("绿色") {
String getName() {
return "绿色";
}
},
;
private String description;
private static Random random = new Random(4);
abstract String getName();
ColorEnum(String description){
this.description = description;
}
public String getDescription() {
return description;
}
@Override
public String toString(){
return "enum:" + this.name();
}
public static ColorEnum next(){
return values()[random.nextInt(values().length)];
}
public static void main(String[] args){
for(ColorEnum colorEnum : ColorEnum.values()) {
System.out.println(colorEnum.getName());
}
}
}
- 还可以在enum 实例中覆盖 enum 定义的方法。
public enum ColorEnum{
RED("红色"){
public String getName(){
return "红色";
}
},
BLUE("蓝色"){
public String getName(){
return "蓝色";
}
},
GREEN("绿色") {
public String getName() {
return "绿色";
}
},
;
private String description;
private static Random random = new Random(4);
public String getName(){
return "颜色";
}
ColorEnum(String description){
this.description = description;
}
public String getDescription() {
return description;
}
@Override
public String toString(){
return "enum:" + this.name();
}
public static ColorEnum next(){
return values()[random.nextInt(values().length)];
}
public static void main(String[] args){
for(ColorEnum colorEnum : ColorEnum.values()) {
System.out.println(colorEnum.getName());
}
}
}
switch 中使用 enum
public static String getName(ColorEnum colorEnum){
switch (colorEnum){
case RED: return "红色";
case BLUE: return "蓝色";
case GREEN: return "绿色";
default: return null;
}
}
EnumSet
- EnumSet 是为了通过 enum 创建一种替代品,以替代传统的基于 int 的 “位标志”,可以用来表示一些开关信息
- EnumSet 设计时充分考虑的性能,内部将一个 long 值作为比特向量,并且具有很好的表达能力。如果 enum 实例的数量超过了 64(long 的长度)个,会再增加一个 long 。
EnumMap
EnumMap 是一个特殊的 map, 他要求其中的键必须来自一个 enum。由于 enum 的数量有限,所以 Enum 内部可以使用数组实现,所以它的速度也非常快。