第31篇:学习 Java 中的枚举类型

简介: 📖 如果一个变量的取值只可能是固定的几个(如:季节),可以考虑使用枚举类型📖 枚举由一组预定义的常量构成

一、枚举(Enum)

若您想研究一下更加准确的东西,可到官方教程查看。

❓ 如何用 Java 代码实现一个季节类型,季节类型的取值只有四个(春、夏、秋、冬) ❓

(1) 通过类(Class)实现

🌼 如何固定取值只能是四个?
🌼 ① 构造方法私有化
🌼 ② 提供四个季节常量(SPRING、SUMMBER、FALL、WINTER)表示四个季节

季节类:

/**
 * 季节类
 */
public class Season {
    public static final Season SPRING = new Season();
    public static final Season SUMMER = new Season();
    public static final Season FALL = new Season();
    public static final Season WINTER = new Season();

    /**
     * 构造方法私有化
     */
    private Season() {

    }
}

根据不同的季节, 打印不同的诗句:

public class TestDemo {
    public static void main(String[] args) {
        Season spring = Season.SPRING;
        Season summer = Season.SUMMER;
        Season fall = Season.FALL;
        Season winter = Season.WINTER;

        // 墙角数枝梅,凌寒独自开。
        printPoem(winter);
        // 春来我不先开口,哪个虫儿敢作声。
        printPoem(spring);
        // 秋风萧瑟,洪波涌起。
        printPoem(fall);
        // 力尽不知热,但惜夏日长。
        printPoem(summer);
    }

    public static void printPoem(Season season) {
        if (season == Season.SPRING) {
            System.out.println("春来我不先开口,哪个虫儿敢作声。");
        } else if (season == Season.SUMMER) {
            System.out.println("力尽不知热,但惜夏日长。");
        } else if (season == Season.FALL) {
            System.out.println("秋风萧瑟,洪波涌起。");
        } else if (season == Season.WINTER) {
            System.out.println("墙角数枝梅,凌寒独自开。");
        }
    }
}

在这里插入图片描述

☘️ 用类实现的季节类型不支持 switch 语句
☘️ switch 中不能放自定义类型
☘️ 枚举(Enum)就可以,而且使用很简单

(2) 通过枚举(Enum)实现

📖 如果一个变量的取值只可能是固定的几个(如:季节),可以考虑使用枚举类型

📖 枚举由一组预定义的常量构成

根据不同季节打印诗句(通过枚举实现)

/**
 * 枚举实现季节类型
 */
public enum Season {
    SPRING, SUMMER, FALL, WINTER
}
public class DemoTest {
    public static void main(String[] args) {
        // 墙角数枝梅,凌寒独自开。
        printPoem(Season.WINTER);
        // 春来我不先开口,哪个虫儿敢作声。
        printPoem(Season.SPRING);
        // 秋风萧瑟,洪波涌起。
        printPoem(Season.FALL);
        // 力尽不知热,但惜夏日长。
        printPoem(Season.SUMMER);
    }

    private static void printPoem(Season season) {
        switch (season) {
            case SPRING:
                System.out.println("春来我不先开口,哪个虫儿敢作声。");
                break;
            case SUMMER:
                System.out.println("力尽不知热,但惜夏日长。");
                break;
            case FALL:
                System.out.println("秋风萧瑟,洪波涌起。");
                break;
            default:
                System.out.println("墙角数枝梅,凌寒独自开。");
                break; 
        }
    }
}

在这里插入图片描述

(3) 枚举的方法

看 name() 和 ordinal() 方法的打印结果, 思考其作用:

public class DemoTest {
    public static void main(String[] args) {
        // SPRING
        System.out.println(Season.SPRING.name());
        // SUMMER
        System.out.println(Season.SUMMER.name());
        // FALL
        System.out.println(Season.FALL.name());
        // WINTER
        System.out.println(Season.WINTER.name());

        // 0
        System.out.println(Season.SPRING.ordinal());
        // 1
        System.out.println(Season.SUMMER.ordinal());
        // 2
        System.out.println(Season.FALL.ordinal());
        // 3
        System.out.println(Season.WINTER.ordinal());
    }
}

在这里插入图片描述

🌻 ① name(): return the name of this enum constant【返回枚举常量的名字】
🌻 ② ordinal(): return the ordinal of this enumeration constant【返回枚举常量的顺序号】

在这里插入图片描述

(4) 枚举细节

🌼 枚举的本质是类(所有枚举类型最终都隐式继承自java.lang.Enum
🌼 枚举定义完常量之后,可以再定义成员变量、成员方法等内容(此时最后一个常量要以分号结尾)

public enum Season {
    SPRING, SUMMER, FALL, WINTER;

    private int number = 4;

    private int returnNum() {
        return number;
    }
}

🌼 常量必须写在成员变量、成员方法的前面


🌼 枚举的构造方法的权限必须是private(不写的话,默认也是private

🌼 Java 会自动调用构造方法以初始化每一个常量(您不能主动调用枚举类型的构造方法)【枚举类型中常量的个数决定了枚举类型的构造方法会被自动调用几次】

看下面的代码,思考打印结果:

public enum Gender {
    BOY, GIRL;

    public static int number;

    Gender() {
        addNumber();
    }

    private void addNumber() {
        number++;
    }
}
public class DemoTest {
    public static void main(String[] args) {
        // output: 3_BOY
        System.out.println(Gender.number +
                Gender.GIRL.ordinal() + "_" + Gender.BOY);
    }
}

(5) 枚举类型有参数的构造方法

public enum Season {
    SPRING(5, 15),
    SUMMER(25, 35),
    FALL(15, 25),
    WINTER(-5, 5);

    private int min;
    private int max;

    Season(int min, int max) {
        this.max = max;
        this.min = min;
    }

    public int getMin() {
        return min;
    }

    public int getMax() {
        return max;
    }
}

二、通过 javap 看枚举的底层

✒️ 枚举英文:Enumeration(简写:Enum)
✒️ 枚举是一组常量的集合
✒️ 可以这样理解:枚举是一种特殊的类,类中包含一组有限的特定的对象
✒️ 枚举通过enum关键字创建


在这里插入图片描述
通过 javap 命令把下面的代码的 class 文件反编译为字节码文件:

/**
 * @author 庆医
 * @describe 性别枚举
 */
public enum Gender {
    MALE, FEMALE
}

在这里插入图片描述

🍀 从反编译结果可知:
✒️① 枚举的底层是一个被 final修饰的类
✒️② 该类默认继承 java.lang.Enum
✒️③ 枚举中的枚举常量本质是类中 static final常量
✒️④ 枚举类中默认有 values() 方法(返回枚举常量组成的数组)
✒️⑤ 枚举类中默认有 valueOf() 方法(通过枚举常量名返回枚举常量对象)
✒️⑥ 枚举类中默认有静态代码块
/**
 * @author 庆医
 * @describe 测试类
 */
public class TestMain {
    public static void main(String[] args) {
        Gender[] values = Gender.values();
        // 1
        System.out.println(values[0].ordinal() + Gender.FEMALE.ordinal());
        // FEMALE_FEMALE
        System.out.println(values[1].name() + "_" + Gender.FEMALE.name());

        // 1
        System.out.println(Gender.valueOf("FEMALE").ordinal());

        // No enum constant com.gq.Gender.BOY
        // 通过字符串【BOY】无法找到枚举常量
        System.out.println(Gender.valueOf("BOY").ordinal());
    }
}

✒️ 枚举底层继承了java.lang.Enum类,所有枚举类不能再继承其他类了
✒️ 但是枚举类依然可以实现接口

public class TestDemo {
    public static void main(String[] args) {
        // output: 玩手机游戏
        People.BOY.play();

        // output: 睡觉觉
        People.GIRL.sleep();
    }
}

interface IDo {
    void play();

    void sleep();
}

enum People implements IDo {
    GIRL, BOY;

    @Override
    public void play() {
        System.out.println("玩手机游戏");
    }

    @Override
    public void sleep() {
        System.out.println("睡觉觉");
    }
}

三、枚举类型的成员方法

☘️ 枚举底层的类继承 java.lang.Enum类,Enum 类中有一些默认的成员方法
✒️① toString(): return the name of this enum constant【返回枚举常量的常量名】
✒️ ② name(): return the name of this enum constant【返回枚举常量的常量名】
✒️ ③ ordinal(): return the ordinal of this enumeration constant【返回枚举常量的顺序号】
✒️ ④ compareTo(): 比较两个枚举常量的顺序号
public enum Gender {
    GIRL, BOY
}

class MainTest {
    public static void main(String[] args) {
        // 1(BOY 常量的顺序号 - GIRL 常量的顺序号)
        System.out.println(Gender.BOY.compareTo(Gender.GIRL));

        // -1(GIRL 常量的顺序号 - BOY 常量的顺序号)
        System.out.println(Gender.GIRL.compareTo(Gender.BOY));

        // 0 (顺序号一样)
        System.out.println(Gender.BOY.compareTo(Gender.BOY));
    }
}

下图是枚举类的 compareTo 方法的底层代码:
在这里插入图片描述

四、Exercise

(1) 第1题

看下面代码的输出结果:

/**
 * @author 庆医
 * @describe 习题1
 */
public class Exercise1 {
    public static void main(String[] args) {
        Gender b = Gender.BOY;
        Gender boy = Gender.BOY;

        // output: BOY
        System.out.println(boy.toString());
        // output: true
        System.out.println(b == Gender.values()[0]);
        // output: true
        System.out.println(boy == Gender.values()[0]);

        boolean tOrf = Gender.values()[1].toString().equals(Gender.GIRL.name());
        // output: true
        System.out.println(tOrf);
    }
}

enum Gender {
    BOY, GIRL
}
☘️ 枚举底层的类继承 java.lang.Enum类,Enum 类中的 toString()方法实际返回的是枚举常量名
在这里插入图片描述

(2) 第2题(编程题)

📗 ① 声明 Week 枚举类,其中包含星期一到星期天等7个常量的定义
📗 ② 使用 values() 方法返回枚举常量数组(遍历该数组,输出中文的星期)
/**
 * @author 庆医
 * @describe 习题2
 */
public class Exercise2 {
    public static void main(String[] args) {
        Week[] weeks = Week.values();

        System.out.println("\n新的一周又开始了,祝你度过:\n");
        for (Week week : weeks) {
            switch (week) {
                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:
                    System.out.println("休闲星期六");
                    break;
                case SUNDAY:
                    System.out.println("潇洒星期天");
                    break;
            }
        }
        System.out.println("\n总之快乐每一天!");
    }
}

enum Week {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY,
    SUNDAY
}

在这里插入图片描述

个人感觉枚举类型不是很难。如有错误,请不吝赐教!

相关文章
|
2月前
|
XML Java 编译器
Java学习十六—掌握注解:让编程更简单
Java 注解(Annotation)是一种特殊的语法结构,可以在代码中嵌入元数据。它们不直接影响代码的运行,但可以通过工具和框架提供额外的信息,帮助在编译、部署或运行时进行处理。
91 43
Java学习十六—掌握注解:让编程更简单
|
23天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
2月前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
36 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
1月前
|
JavaScript Java 项目管理
Java毕设学习 基于SpringBoot + Vue 的医院管理系统 持续给大家寻找Java毕设学习项目(附源码)
基于SpringBoot + Vue的医院管理系统,涵盖医院、患者、挂号、药物、检查、病床、排班管理和数据分析等功能。开发工具为IDEA和HBuilder X,环境需配置jdk8、Node.js14、MySQL8。文末提供源码下载链接。
|
2月前
|
小程序 Oracle Java
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
这篇文章是关于JVM基础知识的介绍,包括JVM的跨平台和跨语言特性、Class文件格式的详细解析,以及如何使用javap和jclasslib工具来分析Class文件。
50 0
JVM知识体系学习一:JVM了解基础、java编译后class文件的类结构详解,class分析工具 javap 和 jclasslib 的使用
|
2月前
|
存储 算法 Java
带你学习java的数组军队列
带你学习java的数组军队列
35 0
|
2月前
|
Java 大数据 开发工具
java学习——环境准备(1)
java学习——环境准备(1)
42 0
|
7月前
|
存储 安全 Java
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
91 1
|
7月前
|
存储 Java
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法
【JAVA学习之路 | 进阶篇】Map接口及其实现类及常用方法
|
7月前
|
Java 测试技术 C++
【JAVA学习之路 | 进阶篇】File类及常用方法
【JAVA学习之路 | 进阶篇】File类及常用方法