• 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
    }
    

    在这里插入图片描述

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

  • 相关阅读:
    大任务拆分,让并行嗨起来!
    设计模式之【建造者模式】
    Java实现的基于欧式距离的聚类算法的Kmeans作业
    vscode 无法激活conda虚拟环境
    ctfshow web入门 web338--web344
    WPF XAML中使用依赖属性
    【论文阅读】Optimal Auctions Through Deep Learning
    GAN:生成对抗网络 Generative Adversarial Networks
    Java代码实现两个数据库之间的数据同步
    中的your-spark-app.jar是个jars包,还是jar文件,如果是jar文件该怎么找
  • 原文地址:https://blog.csdn.net/m0_54189068/article/details/127088296