Java枚举:小小enum,优雅而干净

简介: Java枚举:小小enum,优雅而干净 《Java编程思想》中有这么一句话:“有时恰恰因为它,你才能够‘优雅而干净’地解决问题”——这句话说的是谁呢?就是本篇的主角——枚举(Enum)——大家鼓掌了。

Java枚举:小小enum,优雅而干净

《Java编程思想》中有这么一句话:“有时恰恰因为它,你才能够‘优雅而干净’地解决问题”——这句话说的是谁呢?就是本篇的主角——枚举(Enum)——大家鼓掌了。

在之前很长时间一段时间里,我都不怎么用枚举,因为总感觉它没什么用处——这其实就是“自我认知”的短见。当一个人一直蹲在自己的深井里而不敢跳出来的话,那他真的只能看到井口那么大点的天空

随着时间的推移,我做的项目越来越多,和枚举见面的机会也越来越多,于是我就渐渐地对它越来越有兴趣,研究得多了,才发现原来枚举如此的优秀。

1)枚举的常规用法

一个精简的枚举非常的干净优雅,见下例。

public enum Chenmo {
    WANGER, WANGSAN, WANGSI
}

我们为沉默枚举创建了三个值,分别是王二、王三、王四。这段代码实际上调用了3次Enum(String name, int ordinal)(ordinal单词的意思为顺序),也就是:

new Enum<Chenmo>("WANGER"0);
new Enum<Chenmo>("WANGSAN"1);
new Enum<Chenmo>("WANGSI"2);

我们来遍历输出一下枚举:

for (Chenmo e : Chenmo.values()) {
    System.out.println(e);
}
//输出
//WANGER
//WANGSAN
//WANGSI

2)作为switch的判断条件

使用枚举作为switch语句判断条件能让我们的代码可读性更强,示例如下。

Chenmo key = Chenmo.WANGER;
switch (key) {
case WANGSI:
    System.out.println("今天我送出一个CSDN大鼠标垫");
    break;
case WANGSAN:
    System.out.println("今天我被坑一个CSDN学院年卡");
    break;
default:
    System.out.println("今天我一边高兴,一边失落");
    break;
}

在通过case关键字判断的时候,可以直接使用枚举值,非常简洁。另外,在编译期间限定类型,可以有效的避免越界的情况——字符串常量类型在作为switch判断条件的时候很容易因为误写而发生越界问题。

3)枚举实现单例

《Effective Java》一书中对使用枚举实现单例的方式推崇备至:

使用枚举实现单例的方法虽然还没有广泛采用,但是单元素的枚举类型已经成为实现Singleton的最佳方法。

我觉得“虽然还没有广泛采用”几个字可以去掉了,时至今日,大家应该都知道:使用枚举实现单例是一种非常好的方式。

先来看“双重校验锁”实现的单例:

public class SingleTon2 {

     // 私有化构造方法
    private SingleTon2() {
    };

    private static volatile SingleTon2 singleTon = null;

    public static SingleTon2 getInstance() {

        // 第一次校验
        if (singleTon == null) {
            synchronized (SingleTon2.class) {
                // 第二次校验
                if (singleTon == null) {
                    singleTon = new SingleTon2();
                }
            }
        }
        return singleTon;
    }
}

再来看枚举实现的单例:

public enum SingleTon {

     INSTANCE;

    public void method() {
        System.out.println("我很快乐!");
    }
}

不比不知道,一比吓一跳啊!枚举方式的单例简单到爆——为了不至于看起来太过精简,我还加了一个输出“我很快乐”的方法。

枚举实现的单例可轻松地解决两个问题:

①、线程安全问题。因为Java虚拟机在加载枚举类的时候,会使用ClassLoader的loadClass方法,这个方法使用了同步代码块来保证线程安全。

②、避免反序列化破坏单例。因为枚举的反序列化并不通过反射实现。

4)枚举可与数据库交互

我们可以配合Mybatis将数据库字段转换为枚举类型。现在假设有一个数据库字段check_type的类型如下:

`check_type` int(1) DEFAULT NULL COMMENT '检查类型(1:未通过、2:通过)',

它对应的枚举类型为CheckType,代码如下:

public enum CheckType {
    NO_PASS(0"未通过"), PASS(1"通过");
    private int key;

    private String text;

    private CheckType(int key, String text) {
        this.key = key;
        this.text = text;
    }

    public int getKey() {
        return key;
    }

    public String getText() {
        return text;
    }

    private static HashMap<Integer,CheckType> map = new HashMap<Integer,CheckType>();
    static {
        for(CheckType d : CheckType.values()){
            map.put(d.key, d);
        }
    }

    public static CheckType parse(Integer index) {
        if(map.containsKey(index)){
            return map.get(index);
        }
        return null;
    }
}

CheckType枚举类比我们刚开始见到的那个Chenmo枚举类要复杂一些。

第一,CheckType新添加了构造方法,还有两个字段,key为int型,text为String型。

第二,CheckType中有一个public static CheckType parse(Integer index)方法,可将一个Integer通过key的匹配转化为枚举类型。

那么现在,我们可以在Mybatis的配置文件中使用typeHandler将数据库字段转化为枚举类型。

<resultMap id="CheckLog" type="com.entity.CheckLog">
  <id property="id" column="id"/>
  <result property="checkType" column="check_type" typeHandler="com.CheckTypeHandler"></result>
</resultMap>

其中checkType字段对应的类如下:

public class CheckLog implements Serializable {

    private String id;
    private CheckType checkType;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public CheckType getCheckType() {
        return checkType;
    }

    public void setCheckType(CheckType checkType) {
        this.checkType = checkType;
    }
}

CheckTypeHandler转换器的类源码如下:

public class CheckTypeHandler extends BaseTypeHandler<CheckType{

    @Override
    public CheckType getNullableResult(ResultSet rs, String index) throws SQLException {
        return CheckType.parse(rs.getInt(index));
    }

    @Override
    public CheckType getNullableResult(ResultSet rs, int index) throws SQLException {
        return CheckType.parse(rs.getInt(index));
    }

    @Override
    public CheckType getNullableResult(CallableStatement cs, int index) throws SQLException {
        return CheckType.parse(cs.getInt(index));
    }

    @Override
    public void setNonNullParameter(PreparedStatement ps, int index, CheckType val, JdbcType arg3) throws SQLException {
        ps.setInt(index, val.getKey());
    }
}

CheckTypeHandler 的核心功能就是调用CheckType枚举类的parse()方法对数据库字段进行转换。

5)枚举会比静态常量更消耗内存吗?

说完枚举最常用的4个知识点后,我们来讨论一下“枚举会比静态常量更消耗内存吗?”这个话题——知乎上有人问这样的问题,还有很多人参与回答。

按我的理解,问这个问题的人就好像是在问“0.000,001”比“0.000,000,99”大吗?你说是吗?

原文地址https://www.cnblogs.com/qing-gee/p/10455969.html

相关文章
|
11天前
|
安全 Java 测试技术
🎉Java零基础:全面解析枚举的强大功能
【10月更文挑战第19天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
97 60
|
2月前
|
安全 Java 索引
Java——反射&枚举
本文介绍了Java反射机制及其应用,包括获取Class对象、构造方法、成员变量和成员方法。反射允许在运行时动态操作类和对象,例如创建对象、调用方法和访问字段。文章详细解释了不同方法的使用方式及其注意事项,并展示了如何通过反射获取类的各种信息。此外,还介绍了枚举类型的特点和使用方法,包括枚举的构造方法及其在反射中的特殊处理。
60 9
Java——反射&枚举
|
2月前
|
Java
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
java小工具util系列4:基础工具代码(Msg、PageResult、Response、常量、枚举)
79 5
|
2月前
|
安全 Java 开发者
Java 枚举(enum)详解
Java 中的枚举(`enum`)是一种特殊的数据类型,用于定义一组固定的常量,提升代码的类型安全性和可读性。枚举使用 `enum` 关键字定义,支持方法和构造函数,具有类型安全、单例、自动序列化等特点,并且可以遍历和用于 `switch` 语句中。实际应用包括状态机、指令集、类型标识等场景。枚举使代码更加清晰易维护。
|
3月前
|
Java
Java枚举使用的基本案例
这篇文章是关于Java枚举的基本使用,通过一个指令下发的代码案例,展示了如何定义枚举、使用枚举以及如何通过枚举实现指令的匹配和处理。
|
3月前
|
Java 开发者
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案
在Java编程中,if-else与switch作为核心的条件控制语句,各有千秋。if-else基于条件分支,适用于复杂逻辑;而switch则擅长处理枚举或固定选项列表,提供简洁高效的解决方案。本文通过技术综述及示例代码,剖析两者在性能上的差异。if-else具有短路特性,但条件增多时JVM会优化提升性能;switch则利用跳转表机制,在处理大量固定选项时表现出色。通过实验对比可见,switch在重复case值处理上通常更快。尽管如此,选择时还需兼顾代码的可读性和维护性。理解这些细节有助于开发者编写出既高效又优雅的Java代码。
47 2
|
4月前
|
Java
Java里的enum类型可以用这swich里吗
Java里的enum类型可以用这swich里吗
30 9
|
3月前
|
安全 Java 编译器
|
4月前
|
存储 缓存 Java
java枚举消除冗余代码问题之findByName和findByValue方法工作时的问题如何解决
java枚举消除冗余代码问题之findByName和findByValue方法工作时的问题如何解决
|
4月前
|
安全 Java
Java进阶之枚举
【7月更文挑战第11天】Java枚举是Java 5引入的特性,用于定义固定常量集合,如星期。枚举是继承自`java.lang.Enum`的特殊类,编译后成为final类,每个枚举值是静态final实例。定义枚举用`enum`关键字,如`public enum Weekday {MONDAY, TUESDAY, ...}`。枚举可包含方法和变量,能实现接口但不能继承其他类。例如,`Weekday`枚举可实现`Describe`接口,提供`describe()`方法。在实际应用中,枚举常用于表示如响应状态等固定选项,便于类型安全和代码阅读。
39 8