目录
- 📝 枚举
- 枚举的定义
- 枚举的使用
- 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 {@Overridepublic int getMaxSpeed() {return 150; // 汽车的最大速度}},MOTORCYCLE {@Overridepublic int getMaxSpeed() {return 180; // 摩托车的最大速度}},BICYCLE {@Overridepublic 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 {@Overridepublic double applyDiscount(double price) {return price; // 不打折}},SUMMER_SALE {@Overridepublic double applyDiscount(double price) {return price * 0.9; // 夏季促销打折 10%}},WINTER_SALE {@Overridepublic 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.0System.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) {// 创建一个包含所有星期几的 EnumSetEnumSet<Day> allDays = EnumSet.allOf(Day.class);System.out.println("All days: " + allDays);// 创建一个包含指定枚举常量的 EnumSetEnumSet<Day> weekend = EnumSet.of(Day.SATURDAY, Day.SUNDAY);System.out.println("Weekend: " + weekend);// 创建一个空的 EnumSetEnumSet<Day> noDays = EnumSet.noneOf(Day.class);System.out.println("No days: " + noDays);// 创建一个包含某个范围内枚举常量的 EnumSetEnumSet<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 枚举
-
菜鸟教程