【Java】枚举 Enum

枚举 Enum

枚举的主要用途是:将一组常量组织起来,在这之前表示一组常量通常使用定义常量的方式:

javascript 复制代码
public static int final RED = 1;
public static int final GREEN = 2;
public static int final BLACK = 3;

这样不便于统一组织起来进行管理。

现在我们可以直接用枚举来进行组织,这样一来,就拥有了类型,枚举类型。而不是普通的整形

javascript 复制代码
public enum TestEnum {
    RED,BLACK,GREEN
}

注意:这里面的 RED,BLACK,GREEN 不是 TestEnum 的属性,而是 TestEnum 这个枚举类型的枚举常量!也就是这个类型的实例。
通过反编译就可以看到,这几个实例是在类加载的 Initialization 阶段创建的,并且在静态代码块执行之前创建。

优点:将常量组织起来统一进行管理

场景:错误状态码,消息类型,颜色的划分,状态机等等...

本质:枚举是 java.lang.Enum 的子类,也就是说,自己写的枚举类,就算没有显示的继承 Enum ,但是默认继承了这个类。

枚举的使用

比如:switch语句

javascript 复制代码
public enum TestEnum {
    RED,BLACK,GREEN,WHITE;
    public static void main(String[] args) {
        TestEnum testEnum = TestEnum.BLACK;
        switch (testEnum) {
            case RED:
                System.out.println("red");
                break;
            case BLACK:
                System.out.println("black");
                break;
            case WHITE:
                System.out.println("WHITE");
                break;
            case GREEN:
                System.out.println("black");
                break;
            default:
                break;
        }
    }
}

Enum 类的常用方法

方法名称 描述
values() 以数组形式返回枚举类型的所有成员
ordinal() 获取枚举成员的索引位置(从 0 开始)
valueOf() 将普通字符串转换为枚举实例(注意这个字符串必须与存在的某个实例相同)
compareTo() 比较两个枚举成员在定义时的顺序(其实比较的就是 ordinal() 的值)

因为 我们定义的枚举类默认继承了 Enum 类,所以我们能调用上述方法,但是 Enum 类中并没有 values() 方法。
编写自定义的enum时,其中是不含values()方法的,再编译java文件时,java编译器会自动帮助我们生成这个方法。

  • 示例一:
javascript 复制代码
public enum TestEnum {
    RED,BLACK,GREEN,WHITE;
    public static void main(String[] args) {
    	// 获取所有的实例
        TestEnum[] testEnum2 = TestEnum.values();
        for (int i = 0; i < testEnum2.length; i++) {
            System.out.println(testEnum2[i] + " " + testEnum2[i].ordinal()); // 获得实例以及对应的下标
        }
        System.out.println("=========================");
        // 将普通字符串转换为枚举实例, 但是这个 字符串 必须与已经创建好的实例名字相同
        System.out.println(TestEnum.valueOf("GREEN")); // 有点类似于 Integer.valueOf(),只不过这个限制了范围
        System.out.println(TestEnum.valueOf("GREEN2")); // 报错, 因为 不存在 名为 GREEN2 的枚举常量
    }
}
  • 示例二:
javascript 复制代码
public enum TestEnum {
	// 下标分别为 0 1 2 3 
    RED,BLACK,GREEN,WHITE;
    public static void main(String[] args) {
        //拿到枚举实例BLACK
        TestEnum testEnum = TestEnum.BLACK;
        //拿到枚举实例RED
        TestEnum testEnum21 = TestEnum.RED;
        System.out.println(testEnum.compareTo(testEnum21)); // 比较的就是下标
        System.out.println(BLACK.compareTo(RED));
        System.out.println(RED.compareTo(BLACK));
    }
}

在Java当中枚举实际上就是一个类。所以我们在定义枚举的时候,还可以像下面这样定义和使用枚举:

javascript 复制代码
public enum TestEnum {
	// 这几个表示直接通过构造函数在类内部创建几个实例,语法就是这么写的
    RED("red", 1), BLACK("black", 2), WHITE("white", 3), GREEN("green", 4); // 这几个实例中的参数就对应下面构造方法中的参数
	// 下面这两个才是 枚举类型的属性
    private String name;
    private int key;

    /**
     * 1、当枚举对象有参数后,需要提供相应的构造函数
     * 2、枚举的构造函数默认是私有的 这个一定要记住
     */
    private TestEnum(String name, int key) {
        this.name = name;
        this.key = key;
    }

	// 方法:根据 key 获得对应的 实例
    public static TestEnum getEnumByKey(int key) {
        for (TestEnum t : TestEnum.values()) {
            if (t.key == key) {
                return t;
            }
        }
        return null;
    }

    public static void main(String[] args) {
        System.out.println(getEnumByKey(2));
    }
}

注意:枚举的构造方法默认是私有的,所以外部根本不能创建枚举的实例,所以我们才要在 枚举类型中直接创建出实例,这样外部就能取得实例。
同样因为构造方法是私有的,只能获取已经创建好的实例,那么这个实例就是唯一的。
并且不能通过反射创建枚举实例,所以使用 枚举实现单例模式是安全的。

枚举优缺点

优点:

  • 枚举常量更简单安全 。
  • 枚举具有内置方法 ,代码更优雅

缺点:

  • 不可继承,无法扩展

枚举是否可以通过反射,拿到实例对象呢?

不能!

枚举类型在进行反射创建实例时被过滤了,不能通过反射获取枚举类的实例!所以枚举实现单例模式是安全的。

用枚举实现一个单例模式

javascript 复制代码
public enum TestEnum {
    INSTANCE;
    public TestEnum getInstance(){
        return INSTANCE;
    }

    public static void main(String[] args) {
        TestEnum singleton1=TestEnum.INSTANCE;
        TestEnum singleton2=TestEnum.INSTANCE;
        System.out.println("两个实例是否相同:"+(singleton1==singleton2));
    }
}

总结:

1、枚举本身就是一个类,其构造方法默认为私有的,且都是默认继承于 java.lang.Enum。

2、枚举可以避免反射和序列化问题。

3、枚举常量更简单安全, 枚举具有内置方法 ,代码更优雅, 但是由于构造方法私有所以不可继承,无法扩展。

好啦! 以上就是对 Java 枚举 的讲解,希望能帮到你 !
评论区欢迎指正 !

相关推荐
烟雨书信1 分钟前
Linux中MySQL的逻辑备份与恢复
linux·运维·mysql
一千柯橘4 分钟前
python 项目搭建(类比 node 来学习)
python
sduwcgg9 分钟前
python的numpy的MKL加速
开发语言·python·numpy
大模型真好玩11 分钟前
可视化神器WandB,大模型训练的必备工具!
人工智能·python·mcp
wkj00112 分钟前
QuaggaJS 配置参数详解
java·linux·服务器·javascript·quaggajs
东方佑12 分钟前
使用 Python 自动化 Word 文档样式复制与内容生成
python·自动化·word
钢铁男儿18 分钟前
Python 接口:从协议到抽象基 类(定义并使用一个抽象基类)
开发语言·python
databook26 分钟前
当机器学习遇见压缩感知:用少量数据重建完整世界
python·机器学习·scikit-learn
异常君1 小时前
MyBatis 中 SqlSessionFactory 和 SqlSession 的线程安全性深度分析
java·面试·mybatis
藥瓿亭1 小时前
K8S认证|CKS题库+答案| 5.日志审计
linux·运维·docker·云原生·容器·kubernetes·cka