77. Java 枚举类 - 什么时候使用枚举?
✅ 适合使用枚举的情况
- 变量只能有固定的几个值(比如:星期、月份、交通灯颜色)。
- 需要更安全、更直观的代码(避免拼写错误,防止非法值)。
- 枚举值需要有额外信息或行为(比如
isWeekday()、display())。
❌ 不适合使用枚举的情况
- 值的范围是动态的(比如:数据库查询的用户角色)。
- 值的范围特别大(比如:用户 ID、订单编号)。
如何访问、计算和比较枚举?
在 Java 中,枚举是一种特殊的类,它的所有实例都是编译时确定的常量**。我们可以用 == 来比较枚举值,也可以在 switch 语句或表达式中使用它们,从而写出更可读、安全的代码。
1️⃣ 枚举值可以当作常量
DayOfWeek weekStart = DayOfWeek.MONDAY;
📌 解析
weekStart是一个DayOfWeek类型的变量,它的值是MONDAY。- 枚举值本质上是常量,所以可以直接赋值给枚举变量。
2️⃣ 用 == 比较枚举
在 Java 中,枚举值是单例的(JVM 只会创建一个实例),所以可以用 == 直接比较,而不需要 equals() 方法。
if (weekStart == DayOfWeek.MONDAY) {
System.out.println("The week starts on Monday.");
}
✅ 为什么用 == 比 equals() 更好?
- 性能更高(不涉及对象比较,直接比较引用)。
- 更安全(不会出现
NullPointerException)。 - 更直观(
weekStart == DayOfWeek.MONDAY可读性比weekStart.equals(DayOfWeek.MONDAY)高)。
3️⃣ 用 switch 处理枚举
传统 switch 语法
DayOfWeek someDay = DayOfWeek.FRIDAY;
switch (someDay) {
case MONDAY:
System.out.println("The week just started.");
break;
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
System.out.println("We are somewhere in the middle of the week.");
break;
case FRIDAY:
System.out.println("The weekend is near.");
break;
case SATURDAY:
case SUNDAY:
System.out.println("Weekend");
break;
default:
throw new AssertionError("Should not happen");
}
📌 解析
switch语句让代码更清晰,不需要写多个if-else。- 多个
case可以合并(比如TUESDAY, WEDNESDAY, THURSDAY共享同一个case)。 - 必须加
break,否则会继续执行下一个case(除非使用->语法)。
4️⃣ 用 switch 表达式(Java 12+)
Java 12 引入了 switch 表达式,让代码更简洁。
DayOfWeek someDay = DayOfWeek.FRIDAY;
switch (someDay) {
case MONDAY -> System.out.println("The week just started.");
case TUESDAY, WEDNESDAY, THURSDAY -> System.out.println("We are somewhere in the middle of the week.");
case FRIDAY -> System.out.println("The weekend is near.");
case SATURDAY, SUNDAY -> System.out.println("Weekend");
default -> throw new AssertionError("Should not happen");
}
✅ switch 表达式的优势
- 不需要
break,每个case只会执行对应的代码。 - 语法更简洁,
->让代码更直观。 - 编译器检查完备性,如果
switch里没有处理所有可能的enum值,会报错。
5️⃣ switch 表达式返回值
switch 也可以返回值,让代码更简洁:
DayOfWeek someDay = DayOfWeek.FRIDAY;
String text = switch (someDay) {
case MONDAY -> "The week just started.";
case TUESDAY, WEDNESDAY, THURSDAY -> "We are somewhere in the middle of the week.";
case FRIDAY -> "The weekend is near.";
case SATURDAY, SUNDAY -> "Weekend";
};
System.out.println(text);
📌 解析
switch语句可以直接作为表达式赋值。- 不用
break,代码更清晰。 - 如果漏掉某个
case,编译器会报错,保证逻辑完备。
6️⃣ 遍历所有枚举值
Java 提供了 values() 方法,可以获取所有的枚举值:
for (DayOfWeek day : DayOfWeek.values()) {
System.out.println(day);
}
📌 解析
DayOfWeek.values()返回DayOfWeek枚举的所有值。- 可以用
for循环遍历所有枚举常量。
💡 输出
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
7️⃣ 枚举的 ordinal() 方法
Java 枚举默认有一个 ordinal() 方法,返回枚举的索引(从 0 开始)。
DayOfWeek day = DayOfWeek.WEDNESDAY;
System.out.println(day + " is at position: " + day.ordinal());
💡 输出
WEDNESDAY is at position: 2
📌 解析
MONDAY.ordinal()返回0,TUESDAY.ordinal()返回1,以此类推。- 不推荐用
ordinal()来代替数值,因为如果修改了枚举的顺序,ordinal()值会改变,容易引发 Bug。
8️⃣ 枚举的 compareTo() 方法
枚举默认实现了 compareTo() 方法,可以用 compareTo() 进行顺序比较:
DayOfWeek d1 = DayOfWeek.MONDAY;
DayOfWeek d2 = DayOfWeek.FRIDAY;
if (d1.compareTo(d2) < 0) {
System.out.println(d1 + " comes before " + d2);
} else {
System.out.println(d1 + " comes after " + d2);
}
💡 输出
MONDAY comes before FRIDAY
📌 解析
compareTo()按ordinal()值比较顺序。MONDAY.compareTo(FRIDAY)返回负值,表示MONDAY在FRIDAY之前。
9️⃣ 枚举的 name() 和 toString() 方法
name()方法返回 枚举常量的名字(字符串)。toString()方法默认和name()一样,但可以被重写。
DayOfWeek day = DayOfWeek.MONDAY;
System.out.println(day.name()); // 输出: MONDAY
System.out.println(day.toString()); // 输出: MONDAY
如果我们重写 toString():
public enum DayOfWeek {
MONDAY {
public String toString() {
return "Start of the week";
}
},
FRIDAY {
public String toString() {
return "Almost weekend";
}
},
SUNDAY {
public String toString() {
return "Relaxing day";
}
};
}
💡 输出
Start of the week
🔹 总结
| 方法 | 作用 |
|---|---|
== | 比较两个枚举是否相等(推荐使用) |
switch | 在 switch 语句中使用枚举,提高可读性 |
values() | 获取所有枚举值(for 循环遍历) |
ordinal() | 返回枚举的索引(从 0 开始) |
compareTo() | 按枚举顺序比较大小 |
name() | 获取枚举的名称(字符串) |
toString() | 可以重写,提供更友好的描述 |
希望这个讲解能帮你更清楚地理解 枚举的访问、计算和比较!🚀 🎯