《深入探秘Java中的枚举:掌握Enum的魔力》

😀 准备好了吗?让我们一起步入这座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);
    }
}

📎 参考文章

在这里插入图片描述

  • 22
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天马行空的程序猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值