目录
- 📝 枚举
- 枚举的定义
- 枚举的使用
- 1、表示一组固定常量
- 2、实现接口
- 3、枚举与策略模式
- 4、EnumSet
- 5、EnumMap
- 📎 参考文章
😀 准备好了吗?让我们一起步入这座Java神奇的城堡,探寻枚举(Enum)这个强大工具的奥秘。
📝 枚举
枚举(Enum)是Java中的一个特殊数据类型,继承自 java.lang.Enum,用于定义一组固定的常量。它被用来表示一组有名字的常量,使用起来比定义一组整型或字符串常量更加安全和简洁。
枚举也是一种特殊的类,那它其实是可以定义在一个类的内部的,这样它的作用域就可以限定于这个外部类中使用。
枚举的定义
枚举使用enum
关键字来定义。
public enum Day{
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
编译后的字节码文件:
public final class Day extends Enum<Day> {
// 定义枚举常量,静态最终字段(static final),每个常量都有一个唯一的实例
public static final Day SUNDAY = new Day("SUNDAY", 0);
public static final Day MONDAY = new Day("MONDAY", 1);
public static final Day TUESDAY = new Day("TUESDAY", 2);
public static final Day WEDNESDAY = new Day("WEDNESDAY", 3);
public static final Day THURSDAY = new Day("THURSDAY", 4);
public static final Day FRIDAY = new Day("FRIDAY", 5);
public static final Day SATURDAY = new Day("SATURDAY", 6);
// 包含所有枚举常量的数组,供 values() 方法使用
private static final Day[] $VALUES = { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY };
// 枚举常量的字段,存储名称和序号
private final String name;
private final int ordinal;
// 私有构造函数,防止外部实例化
private Day(String name, int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
// 返回枚举常量的名称
public String name() {
return name;
}
// 返回枚举常量的序号
public int ordinal() {
return ordinal;
}
// 返回所有枚举常量的数组的副本
public static Day[] values() {
return (Day[]) $VALUES.clone();
}
// 根据名称返回对应的枚举常量
public static Day valueOf(String name) {
return (Day) Enum.valueOf(Day.class, name);
}
}
在其他类中定义:
public class Schedule {
//定义枚举
public enum Day{
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
private Day day;
public Schedule(Day day){
this.day = day ;
}
public Day getToday() {
return today;
}
public void setToday(Day today) {
this.today = today;
}
public void printTask() {
switch (today) {
case MONDAY:
System.out.println("今天的任务:参加团队会议。");
break;
case TUESDAY:
System.out.println("今天的任务:编写项目文档。");
break;
case WEDNESDAY:
System.out.println("今天的任务:代码审查和修复漏洞。");
break;
case THURSDAY:
System.out.println("今天的任务:实现新功能。");
break;
case FRIDAY:
System.out.println("今天的任务:部署应用程序。");
break;
case SATURDAY:
case SUNDAY:
System.out.println("今天的任务:休息和充电。");
break;
}
}
public static void main(String[] args) {
// 创建一个 Schedule 对象,表示今天是星期一
Schedule schedule = new Schedule(Day.MONDAY);
schedule.printTask();
// 改变今天的日期为星期五
schedule.setToday(Day.FRIDAY);
schedule.printTask();
}
}
枚举也是不可变类,一旦枚举常量被创建,它们的状态(即枚举的实例)是不能被改变的。所以这可以确保Java虚拟机中仅有一个常量对象。
一般比较两个枚举对象时,采用
==
运算符比较。
==
运算符比较的时候,如果两个对象都为 null,并不会发生NullPointerException
,而equals()
方法则会.
==
运算符会在编译时进行检查,如果两侧的类型不匹配,会提示错误,而equals()
方法则不会。
枚举的使用
1、表示一组固定常量
枚举通常用于表示一组固定的常量,例如星期几、颜色、方向等。
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
2、实现接口
枚举可以实现接口,允许为每个枚举常量定义不同的行为。
// 定义一个接口,声明获取最大速度的方法
public interface Speed {
int getMaxSpeed();
}
// 定义一个枚举类,表示不同的交通工具,并实现 Speed 接口
public enum Vehicle implements Speed {
CAR {
@Override
public int getMaxSpeed() {
return 150; // 汽车的最大速度
}
},
MOTORCYCLE {
@Override
public int getMaxSpeed() {
return 180; // 摩托车的最大速度
}
},
BICYCLE {
@Override
public int getMaxSpeed() {
return 30; // 自行车的最大速度
}
}
}
public class EnumExample {
public static void main(String[] args) {
// 遍历所有交通工具并输出其最大速度
for (Vehicle vehicle : Vehicle.values()) {
System.out.println(vehicle + " 的最大速度是 " + vehicle.getMaxSpeed() + " km/h.");
}
}
}
3、枚举与策略模式
// 定义一个枚举类,表示不同的打折策略
public enum DiscountStrategy {
NO_DISCOUNT {
@Override
public double applyDiscount(double price) {
return price; // 不打折
}
},
SUMMER_SALE {
@Override
public double applyDiscount(double price) {
return price * 0.9; // 夏季促销打折 10%
}
},
WINTER_SALE {
@Override
public double applyDiscount(double price) {
return price * 0.8; // 冬季促销打折 20%
}
};
// 抽象方法,应用打折策略
public abstract double applyDiscount(double price);
}
public class EnumExample {
public static void main(String[] args) {
double originalPrice = 100.0; // 原始价格
DiscountStrategy strategy = DiscountStrategy.SUMMER_SALE; // 选择夏季促销打折策略
double discountedPrice = strategy.applyDiscount(originalPrice); // 计算打折后的价格
System.out.println("原始价格: " + originalPrice); // 输出: Original Price: 100.0
System.out.println("打折后的价格: " + discountedPrice); // 输出: Discounted Price: 90.0
}
}
4、EnumSet
EnumSet
是一个专门处理枚举类型的集合实现(Set接口)。
EnumSet 的创建和使用
EnumSet 是一个抽象类,所以创建 EnumSet 时不能使用 new 关键字。不过,EnumSet 提供了很多有用的静态工厂方法。
-
EnumSet.noneOf(Class<E> elementType)
: 创建一个空的EnumSet
,其中E
是枚举类型。 -
EnumSet.allOf(Class<E> elementType)
: 创建一个包含指定枚举类型所有枚举常量的EnumSet
。 -
EnumSet.of(E e)
: 创建一个只包含指定枚举常量的EnumSet
。 -
EnumSet.of(E e1, E e2, E... rest)
: 创建一个包含指定枚举常量的EnumSet
。 -
EnumSet.range(E from, E to)
: 创建一个包含指定范围内所有枚举常量的EnumSet
。
示例:
import java.util.EnumSet;
// 定义一个枚举类
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public class EnumSetExample {
public static void main(String[] args) {
// 创建一个包含所有星期几的 EnumSet
EnumSet<Day> allDays = EnumSet.allOf(Day.class);
System.out.println("All days: " + allDays);
// 创建一个包含指定枚举常量的 EnumSet
EnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
System.out.println("Weekend: " + weekend);
// 创建一个空的 EnumSet
EnumSet<Day> noDays = EnumSet.noneOf(Day.class);
System.out.println("No days: " + noDays);
// 创建一个包含某个范围内枚举常量的 EnumSet
EnumSet<Day> weekDays = EnumSet.range(Day.MONDAY, Day.FRIDAY);
System.out.println("Weekdays: " + weekDays);
// 向 EnumSet 添加元素(不允许直接添加,需使用添加方法)
noDays.add(Day.MONDAY);
noDays.add(Day.FRIDAY);
System.out.println("No days after adding: " + noDays);
// 执行集合操作
EnumSet<Day> holidays = EnumSet.of(Day.SATURDAY, Day.SUNDAY);
EnumSet<Day> workDays = EnumSet.complementOf(holidays);
System.out.println("Workdays: " + workDays);
}
}
5、EnumMap
EnumMap
是 Java Collections Framework 中的一个特殊的映射实现,专门用于枚举类型的映射。它是 Map
接口的一个实现,优化了对枚举类型的支持,提供了高效的键值对操作。
EnumMap 的创建和使用
EnumMap 不是一个抽象类,需要用 new 关键字来创建。
import java.util.EnumMap;
import java.util.Map;
// 定义一个枚举类
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public class EnumMapExample {
public static void main(String[] args) {
// 创建一个 EnumMap,键为 Day 枚举,值为 String 类型
EnumMap<Day, String> dayMap = new EnumMap<>(Day.class);
// 向 EnumMap 中添加键值对
dayMap.put(Day.MONDAY, "Workday");
dayMap.put(Day.SATURDAY, "Weekend");
dayMap.put(Day.SUNDAY, "Weekend");
// 输出 EnumMap 内容
System.out.println("Day Map: " + dayMap);
// 访问指定键的值
System.out.println("Monday: " + dayMap.get(Day.MONDAY)); // 输出: Workday
// 检查是否包含某个键
System.out.println("Contains Saturday? " + dayMap.containsKey(Day.SATURDAY)); // 输出: true
// 检查是否包含某个值
System.out.println("Contains Weekend value? " + dayMap.containsValue("Weekend")); // 输出: true
// 遍历 EnumMap 并输出键值对
for (Map.Entry<Day, String> entry : dayMap.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
// 移除某个键值对
dayMap.remove(Day.SUNDAY);
System.out.println("Day Map after removing Sunday: " + dayMap);
}
}
📎 参考文章
-
Java 枚举
-
菜鸟教程