31、学习 Java 中的枚举类型

简介: 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
}

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

相关文章
|
3天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
3天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
|
3天前
|
SQL Java 数据库连接
Java从入门到精通:2.3.1数据库编程——学习JDBC技术,掌握Java与数据库的交互
ava从入门到精通:2.3.1数据库编程——学习JDBC技术,掌握Java与数据库的交互
|
3天前
|
设计模式 存储 前端开发
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
Java从入门到精通:2.2.1学习Java Web开发,了解Servlet和JSP技术,掌握MVC设计模式
|
3天前
|
Java API
Java从入门到精通:2.1.5深入学习Java核心技术之文件操作
Java从入门到精通:2.1.5深入学习Java核心技术之文件操作
|
3天前
|
并行计算 算法 安全
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
Java从入门到精通:2.1.3深入学习Java核心技术——掌握Java多线程编程
|
7天前
|
JavaScript Java 测试技术
基于Java的驾考自主学习预约平台的设计与实现(源码+lw+部署文档+讲解等)
基于Java的驾考自主学习预约平台的设计与实现(源码+lw+部署文档+讲解等)
21 0
|
1月前
|
存储 安全 Java
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
24、使用 Java 官方教程学习:① 类变量和类方法详解;② 深入介绍 main() 方法
38 1
|
4月前
|
Java 编译器 C语言
Java学习 7.Java-方法的使用
Java学习 7.Java-方法的使用
45 0
|
10月前
|
Java API
【Java新特性学习 三】JDK8: 语言新特性之方法引用
【Java新特性学习 三】JDK8: 语言新特性之方法引用
76 0