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

news2024/11/15 11:05:34

目录

  • 📝 枚举
    • 枚举的定义
    • 枚举的使用
      • 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 枚举

  • 菜鸟教程

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1946216.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu 修改源地址

注意事项&#xff1a;版本说明&#xff01;&#xff01;&#xff01; Ubuntu24.04的源地址配置文件发生改变。 不再使用以前的 sources.list 文件&#xff0c;该文件内容变成了一行注释&#xff1a; # Ubuntu sources have moved to /etc/apt/sources.list.d/ubuntu.sources…

STM32-FreeRTOS快速学习

定义 FreeRTOS 满足实施系统对任务响应时间的要求。 实时操作系统、轻量级&#xff08;内核小&#xff0c;只需要几KB的ROM和RAM&#xff09;、 提供了一些内核功能&#xff0c;如任务管理、时间管理、内存管理和通信机制等。 和裸机的区别 裸机&#xff1a;无操作系统&…

产品系统的UI暗色系和浅色系模式切换是符合人体视觉工程学的设计

视觉革命&#xff1a;UI设计中的暗夜与黎明 UI设计如同夜空中最亮的星辰&#xff0c;引领着用户穿梭于信息的海洋。而今&#xff0c;一场视觉革命正在悄然上演&#xff0c;它关乎于我们的眼睛&#xff0c;关乎于我们的体验——那就是产品系统的UI暗色系和浅色系模式的切换。如…

【机器学习】Jupyter Notebook如何使用之基本步骤和进阶操作

引言 Jupyter Notebook 是一个交互式计算环境&#xff0c;它允许创建包含代码、文本和可视化内容的文档 文章目录 引言一、基本步骤1.1 启动 Jupyter Notebook1.2 使用 Jupyter Notebook 仪表板1.3 在笔记本中工作1.4 常用快捷键1.5 导出和分享笔记本 二、进阶用法2.1 组织笔…

Excel超级处理器,工作簿文件.xls/.xlsx/.csv相互批量转换

如何将.xlsx文件转成.csv文件&#xff0c;.xls转换成.xlsx文件&#xff0c;以及.xls文件转成.csv文件或.csv转换成.xlsx文件&#xff0c;如果是单个文件转换&#xff0c;那么将当前文件另存为&#xff0c;保存类型&#xff0c;选择即可。如下图所示&#xff1a; 如果是多个文件…

【AutoDL】AutoDL+Xftp+Xshell+VSCode配合使用教程

身边没有显卡资源或不足以训练模型时&#xff0c;可以租赁服务器的显卡。 1、AutoDL Step :注册账号->选择显卡->选择环境->开机启动 1.1 首先打开AutoDL官网&#xff0c;注册账号 1.2 租赁自己想要的显卡资源 1.3 选择基础环境。 此处&#xff0c;我们让其自动配置…

[网络通信原理]——TCP/IP模型—网络层

网络层 网络层概述 网络层位于OSI模型的第三层&#xff0c;它定义网络设备的逻辑地址&#xff0c;也就是我们说的IP地址&#xff0c;能够在不同的网段之间选择最佳数据转发路径。在网络层中有许多协议&#xff0c;其中主要的协议是IP协议。 IP数据包格式 IP数据报是可变长度…

Linux服务器配置Python+PyTorch+CUDA深度学习环境

参考博主Linux服务器配置PythonPyTorchCUDA深度学习环境_linux cuda环境配置-CSDN博客 https://blog.csdn.net/NSJim/article/details/115386936?ops_request_misc&request_id&biz_id102&utm_termlinux%E8%99%9A%E6%8B%9F%E7%8E%AF%E5%A2%83%E6%8C%89pytorch%20c…

微信答题小程序产品研发-需求分析与原型设计

欲知应候何时节&#xff0c;六月初迎大暑风。 我前面说过&#xff0c;我决意仿一款答题小程序&#xff0c;所以我做了大量的调研。 题库软件产品开发不仅仅是写代码这一环&#xff0c;它包含从需求调研、分析与构思、设计到开发、测试再到部署上线一系列复杂过程。 需求分析…

子数组和为k子数组和最大

题目1&#xff1a;子数组和为k /*给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。子数组是数组中元素的连续非空序列。示例 1&#xff1a;输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2 示例 2&#xff1a;输入&a…

微软蓝屏事件对企业数字化转型有什么影响?

引言&#xff1a;从北京时间2024年7月19日&#xff08;周五&#xff09;下午2点多开始&#xff0c;全球大量Windows用户出现电脑崩溃、蓝屏死机、无法重启等情况。事发后&#xff0c;网络安全公司CrowdStrike称&#xff0c;收到大量关于Windows电脑出现蓝屏报告&#xff0c;公司…

make2exe:自动集成测试

模板Makefile&#xff0c;生成多个C/C模块的集成测试程序。

算法学习day19

一、通过删除字母匹配到字符字典中的最大值 给你一个字符串 s 和一个字符串数组 dictionary &#xff0c;找出并返回 dictionary 中最长的字符串&#xff0c;该字符串可以通过删除 s 中的某些字符得到。 如果答案不止一个&#xff0c;返回长度最长且字母序最小的字符串。如果…

花几千上万学习Java,真没必要!(二十六)

1、成员内部类&#xff1a; package internalclass.com; //在Java中&#xff0c;成员内部类&#xff08;也称为非静态内部类&#xff09;是定义在另一个类&#xff08;外部类&#xff09;内部的类。 //成员内部类可以访问外部类的所有成员&#xff08;包括私有成员&#xff09…

【计算机网络】网络层——IPv4地址(个人笔记)

学习日期&#xff1a;2024.7.24 内容摘要&#xff1a;IPv4地址&#xff0c;分类编址&#xff0c;子网&#xff0c;无分类编址 IPv4地址概述 在TCP/IP体系中&#xff0c;IP地址是一个最基本的概念&#xff0c;IPv4地址就是给因特网上的每一台主机的每一个接口分配一个在全世界…

ASP.NET Web Api 使用 EF 6,DateTime 字段如何取数据库服务器当前时间

前言 在做数据库设计时&#xff0c;为了方便进行数据追踪&#xff0c;通常会有几个字段是每个表都有的&#xff0c;比如创建时间、创建人、更新时间、更新人、备注等&#xff0c;在存储这些时间时&#xff0c;要么存储 WEB 服务器的时间&#xff0c;要么存储数据库服务器的时间…

Java之数组应用-冒泡排序-二分查找

冒泡排序 冒泡(Bubble Sort)排序是一种简单排序算法&#xff0c;它通过依次比较交换两个相邻元素实现功能。每一次冒泡会让至少一个元素移动到它应该在的位置上&#xff0c;这样 n 次冒泡就完成了 n 个数据的排序工作。 这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”…

python实现图像缩放算法

图像缩放算法 1.最近邻插值图像缩放算法详解算法步骤Python 实现详细解释 优缺点2.双线性插值图像缩放算法详解算法步骤Python 实现详细解释 优缺点3.双三次插值图像缩放算法详解算法步骤Python 实现详细解释 优缺点 1.最近邻插值图像缩放算法详解 最近邻插值&#xff08;Near…

【网络】计算机网络基础——计算机网络背景和发展、认识网络协议、OSI七层模型、TCP/IP四层模型、网络的传输

文章目录 Linux网络1. 计算机网络背景和发展2. 认识网络协议3. OSI七层模型3.1 物理层3.2 数据链路层3.3 网络层3.4 传输层3.5 会话层3.6 表示层3.7 应用层 4. TCP/IP四层模型5. 网络的传输 Linux网络 1. 计算机网络背景和发展 开始的计算机都是独立模式&#xff08;计算机之间…

与众不同的社交体验:Facebook的新功能与新变化

在快速变化的社交媒体领域&#xff0c;Facebook不断引入创新功能和变化&#xff0c;以满足用户日益增长的需求&#xff0c;并提供与众不同的社交体验。从增强现实到数据隐私&#xff0c;Facebook的新功能和更新正在塑造一个全新的社交平台。本文将深入探讨这些新功能和变化&…