【参考】枚举类名建议带上 Enum 后缀,枚举成员名称需要全大写,单词间用下划线隔开。 说明:枚举其实就是特殊的类,域成员均为常量,且构造方法被默认强制是私有。 正例:枚举名字为 ProcessStatusEnum 的成员名称:SUCCESS / UNKNOWN_REASON。
创建一个枚举类
public enum DayEnum {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
使用
public class EnumTest {
DayEnum day;
public EnumTest(DayEnum day) {
this.day = day;
}
public void tellItLikeItIs() {
switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
case SATURDAY: case SUNDAY:
System.out.println("Weekends are best.");
break;
default:
System.out.println("Midweek days are so-so.");
break;
}
}
public static void main(String[] args) {
EnumTest firstDay = new EnumTest(DayEnum.MONDAY);
firstDay.tellItLikeItIs();
EnumTest thirdDay = new EnumTest(DayEnum.WEDNESDAY);
thirdDay.tellItLikeItIs();
EnumTest fifthDay = new EnumTest(DayEnum.FRIDAY);
fifthDay.tellItLikeItIs();
EnumTest sixthDay = new EnumTest(DayEnum.SATURDAY);
sixthDay.tellItLikeItIs();
EnumTest seventhDay = new EnumTest(DayEnum.SUNDAY);
seventhDay.tellItLikeItIs();
}
}

带构造器枚举类
当存在字段和方法时,枚举常量列表必须以分号结尾,且定义枚举常量在字段和方法之前
枚举类型的构造函数必须是私有(没有修饰符默认为 private),不能自己手动调用枚举类的构造函数,JVM 会自动创建在枚举类中定义的常量。所以看似一样的枚举值一定不相等,因为这可能不是同一个对象实例
/**
* 行星上一个物体的重力和重量
*/
public enum Planet {
MERCURY(3.303e+23, 2.4397e6),
VENUS(4.869e+24, 6.0518e6),
EARTH(5.976e+24, 6.37814e6),
MARS(6.421e+23, 3.3972e6),
JUPITER(1.9e+27, 7.1492e7),
SATURN(5.688e+26, 6.0268e7),
URANUS(8.686e+25, 2.5559e7),
NEPTUNE(1.024e+26, 2.4746e7);
// 以公斤为单位的
private final double mass;
// 以米为单位的
private final double radius;
Planet(double mass, double radius) {
this.mass = mass;
this.radius = radius;
}
private double mass() {
return mass;
}
private double radius() {
return radius;
}
// 万有引力常数 (m3 kg-1 s-2)
public static final double G = 6.67300E-11;
double surfaceGravity() {
return G * mass / (radius * radius);
}
double surfaceWeight(double otherMass) {
return otherMass * surfaceGravity();
}
}
使用
public static void main(String[] args) {
double earthWeight = Double.parseDouble("175");
double mass = earthWeight / EARTH.surfaceGravity();
for (Planet p : Planet.values()) {
System.out.printf("你在 %s 上的体重是 %f%n", p, p.surfaceWeight(mass));
}
}

Enum 相关方法
public static void main(String[] args) {
// 获取所有枚举常量
DayEnum[] values = DayEnum.values();
for (DayEnum value : values) {
System.out.print(value);
// 枚举常量在枚举类中的序号,零开始
System.out.println("\t" + value.ordinal());
}
// 获取指定枚举常量,若不存在会报异常
System.out.println(DayEnum.valueOf("SATURDAY"));
System.out.println(DayEnum.valueOf(DayEnum.class, "SATURDAY"));
// 比较枚举常量,与 == 方式相同,返回布尔值
System.out.println(DayEnum.FRIDAY.equals(DayEnum.FRIDAY));
// 比较枚举常量,采用 ordinal 序号方式,返回数字
System.out.println(DayEnum.FRIDAY.compareTo(DayEnum.FRIDAY));
}

反编译 DayEnum
所有枚举类都隐式继承了抽象类 java.lang.Enum,用 javap 工具可以看到。所以枚举类不能继承其他类,JAVA 中为单继承,多实现
枚举常量会隐式被修饰成公共的静态常量,即枚举常量只会有一个实例,比较时可以使用 ==,枚举类的 equals 方法是 final 修饰
public final class javaenum.DayEnum extends java.lang.Enum<javaenum.DayEnum> {
public static final javaenum.DayEnum SUNDAY;
public static final javaenum.DayEnum MONDAY;
public static final javaenum.DayEnum TUESDAY;
public static final javaenum.DayEnum WEDNESDAY;
public static final javaenum.DayEnum THURSDAY;
public static final javaenum.DayEnum FRIDAY;
public static final javaenum.DayEnum SATURDAY;
public static javaenum.DayEnum[] values();
Code:
0: getstatic #1 // Field $VALUES:[Ljavaenum/DayEnum;
3: invokevirtual #2 // Method "[Ljavaenum/DayEnum;".clone:()Ljava/lang/Object;
6: checkcast #3 // class "[Ljavaenum/DayEnum;"
9: areturn
public static javaenum.DayEnum valueOf(java.lang.String);
Code:
0: ldc #4 // class javaenum/DayEnum
2: aload_0
3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
6: checkcast #4 // class javaenum/DayEnum
9: areturn
static {};
Code:
0: new #4 // class javaenum/DayEnum
3: dup
4: ldc #7 // String SUNDAY
6: iconst_0
7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
10: putstatic #9 // Field SUNDAY:Ljavaenum/DayEnum;
13: new #4 // class javaenum/DayEnum
16: dup
17: ldc #10 // String MONDAY
19: iconst_1
20: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
23: putstatic #11 // Field MONDAY:Ljavaenum/DayEnum;
26: new #4 // class javaenum/DayEnum
29: dup
30: ldc #12 // String TUESDAY
32: iconst_2
33: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
36: putstatic #13 // Field TUESDAY:Ljavaenum/DayEnum;
39: new #4 // class javaenum/DayEnum
42: dup
43: ldc #14 // String WEDNESDAY
45: iconst_3
46: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
49: putstatic #15 // Field WEDNESDAY:Ljavaenum/DayEnum;
52: new #4 // class javaenum/DayEnum
55: dup
56: ldc #16 // String THURSDAY
58: iconst_4
59: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
62: putstatic #17 // Field THURSDAY:Ljavaenum/DayEnum;
65: new #4 // class javaenum/DayEnum
68: dup
69: ldc #18 // String FRIDAY
71: iconst_5
72: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
75: putstatic #19 // Field FRIDAY:Ljavaenum/DayEnum;
78: new #4 // class javaenum/DayEnum
81: dup
82: ldc #20 // String SATURDAY
84: bipush 6
86: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V
89: putstatic #21 // Field SATURDAY:Ljavaenum/DayEnum;
92: bipush 7
94: anewarray #4 // class javaenum/DayEnum
97: dup
98: iconst_0
99: getstatic #9 // Field SUNDAY:Ljavaenum/DayEnum;
102: aastore
103: dup
104: iconst_1
105: getstatic #11 // Field MONDAY:Ljavaenum/DayEnum;
108: aastore
109: dup
110: iconst_2
111: getstatic #13 // Field TUESDAY:Ljavaenum/DayEnum;
114: aastore
115: dup
116: iconst_3
117: getstatic #15 // Field WEDNESDAY:Ljavaenum/DayEnum;
120: aastore
121: dup
122: iconst_4
123: getstatic #17 // Field THURSDAY:Ljavaenum/DayEnum;
126: aastore
127: dup
128: iconst_5
129: getstatic #19 // Field FRIDAY:Ljavaenum/DayEnum;
132: aastore
133: dup
134: bipush 6
136: getstatic #21 // Field SATURDAY:Ljavaenum/DayEnum;
139: aastore
140: putstatic #1 // Field $VALUES:[Ljavaenum/DayEnum;
143: return
}
Enum 源码
/**
* 使用枚举类型作为 Collection 或 Map 中 Key 的类型时
* 可用 {@linkplain java.util.EnumSet set} 和 {@linkplain java.util.EnumMap map} 实现,专业且高效
*/
public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
// 枚举常量的名称,获取时使用{@link #toString}方法而不是访问此字段
private final String name;
// 此方法主要用于在特殊情况下使用
public final String name() {
return name;
}
// 此枚举常数的序数(其位置在枚举声明中,分配初始常量序数为零)
// 专门设计供复杂基于枚举的数据结构使用,例如 {@link java.util.EnumSet} 和 {@link java.util.EnumMap}
private final int ordinal;
public final int ordinal() {
return ordinal;
}
/**
* 唯一构造函数。程序员无法调用,由编译器调用
* @param name 枚举常量的名称,用于声明它的标识符
* @param ordinal 枚举常量的序数(声明它在枚举中的位置,初始常量的序数为零)
*/
protected Enum(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
// 返回声明中包含的此枚举常量的名称,可以覆盖该方法
public String toString() {
return name;
}
public final boolean equals(Object other) {
return this == other;
}
public final int hashCode() {
return super.hashCode();
}
// 保证了枚举类永远不会被克隆
protected final Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
// 返回负整数,零或正整数
// 枚举常量只能与同一枚举类型的其他枚举常量相比较。此方法实现是根据 ordinal 值比较
public final int compareTo(E o) {
Enum<?> other = (Enum<?>) o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
// 返回与此枚举常量的枚举类型对应的 Class 对象
@SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>) clazz : (Class<E>) zuper;
}
/**
* @param enumType 枚举类型的 Class 对象,用于从中返回常量
* @param name 要返回的常量的名称
* @param <T> 要返回常量的其枚举类型
* @return 具有指定名称的指定枚举类型的枚举常量
*/
public static <T extends Enum<T>> T valueOf(Class<T> enumType, String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException("No enum constant " + enumType.getCanonicalName() + "." + name);
}
// 枚举类不能有finalize方法
protected final void finalize() {}
// 默认防止反序列化
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
throw new InvalidObjectException("can't deserialize enum");
}
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("can't deserialize enum");
}
}
https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
https://docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.9
https://www.ibm.com/developerworks/cn/java/j-lo-enum/index.html
https://blog.csdn.net/javazejian/article/details/71333103
来源:https://www.cnblogs.com/jhxxb/p/10536948.html