前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java枚举

Java枚举

原创
作者头像
ruochen
修改2021-11-21 14:53:07
2.4K0
修改2021-11-21 14:53:07
举报

枚举可以做什么

假设我们现在想表达星期,为了避免魔法值的出现,我们可能会写一个常量类:

代码语言:txt
复制
package com.tea.modules.java8.enums;
代码语言:txt
复制
/**
代码语言:txt
复制
 * com.tea.modules.java8.enums <br>
 * 使用抽象类来表达常量,防止被篡改
 * @author jaymin
 * @since 2021/6/9
 */
public abstract class WeekConstant {
    /**
     * 周一
     */
    public static final Integer MON = 1;
    /**
     * 周二
     */
    public static final Integer TUE = 2;
    /**
     * 周三
     */
    public static final Integer WEB = 3;
    /**
     * 周四
     */
    public static final Integer THUR = 4;
    /**
     * 周五
     */
    public static final Integer FRI = 5;
    /**
     * 周六
     */
    public static final Integer SAT = 6;
    /**
     * 周日
     */
    public static final Integer SUN = 7;
}

这样一来,1-7的星期数就可以用WeekConstant.MON这样的方式来表达了,好看了不少,但是仍然存在一定的缺陷。

假设我们现在往WeekConstant中再添加一行:

代码语言:txt
复制
public static final Integer WEEK = 1;

将其传入到一个接收参数为"星期一"的方法中,并不会产生任何问题,因为都能表示1,但是从代码阅读上来看,出现歧义了。

JDK提供了Enum枚举类,让代码可读性更强,同时它也是类型安全的类,所有的枚举类都被final修饰,还可以很好地实现单例模式.

枚举类基础用法

定义一个枚举类

  • Week
代码语言:txt
复制
package com.tea.modules.java8.enums;
代码语言:txt
复制
/**
代码语言:txt
复制
 * com.tea.modules.java8.enums <br>
 * 使用枚举类来表示星期
 *
 * @author jaymin
 * @since 2021/6/9
 */
public enum WeekEnum {
    /**
     * 周一
     */
    MON,
    /**
     * 周二
     */
    TUE,
    /**
     * 周三
     */
    WEB,
    /**
     * 周四
     */
    THUR,
    /**
     * 周五
     */
    FRI,
    /**
     * 周六
     */
    SAT,
    /**
     * 周日
     */
    SUN;
}
  • Demo
代码语言:txt
复制
package com.tea.modules.java8.enums;
代码语言:txt
复制
/**
代码语言:txt
复制
 * com.tea.modules.java8.enums <br>
 * 实战枚举类
 *
 * @author jaymin
 * @since 2021/6/9
 */
public class EnumDemo {
    /**
     * 了解枚举的基本功能
     */
    private static void enumFunction() {
        // 获取所有的枚举信息
        WeekEnum[] weekDays = WeekEnum.values();
        for (WeekEnum weekDay : weekDays) {
            String enumName = "当前枚举名称:" + weekDay.name();
            String enumIndex = " 枚举位置:" + weekDay.ordinal();
            String enumClass = " 枚举类型:" + weekDay.getDeclaringClass();
            System.out.println(enumName + enumIndex + enumClass);
        }
        WeekEnum mon = WeekEnum.valueOf("MON");
        System.out.println(mon.name());
        WeekEnum monB = Enum.valueOf(WeekEnum.class, "MON");
        System.out.println(monB);
    }
代码语言:txt
复制
    public static void main(String[] args) {
代码语言:txt
复制
        enumFunction();
代码语言:txt
复制
    }
代码语言:txt
复制
}

输出结果:

代码语言:txt
复制
当前枚举名称:MON 枚举位置:0 枚举类型:class com.tea.modules.java8.enums.WeekEnum
代码语言:txt
复制
当前枚举名称:TUE 枚举位置:1 枚举类型:class com.tea.modules.java8.enums.WeekEnum
代码语言:txt
复制
当前枚举名称:WEB 枚举位置:2 枚举类型:class com.tea.modules.java8.enums.WeekEnum
代码语言:txt
复制
当前枚举名称:THUR 枚举位置:3 枚举类型:class com.tea.modules.java8.enums.WeekEnum
代码语言:txt
复制
当前枚举名称:FRI 枚举位置:4 枚举类型:class com.tea.modules.java8.enums.WeekEnum
代码语言:txt
复制
当前枚举名称:SAT 枚举位置:5 枚举类型:class com.tea.modules.java8.enums.WeekEnum
代码语言:txt
复制
当前枚举名称:SUN 枚举位置:6 枚举类型:class com.tea.modules.java8.enums.WeekEnum
代码语言:txt
复制
MON
代码语言:txt
复制
MON
API Document

API

描述

name

枚举的名字

Enum.values()

返回一个当前枚举类中的所有枚举元素

ordinal

返回当前枚举在枚举类中的索引,从0开始

getDeclaringClass

返回枚举类的类型

Enum.valueOf()

返回与传入的名称相等的枚举,可能会抛出异常

switch配合枚举类编写状态机

OK,现在我们将需求变动一下:

周一到周五是工作日,输出工作时间;undefined 周六周日是休息日,输出“休息”;

代码语言:txt
复制
/**
代码语言:txt
复制
 * 输入工作日,输出工作时间 <br>
 * 枚举的本质就是int,配合switch的时候,编译会做类似于ordinal来确定int值
 */
private static void printWorkDays(WeekEnum weekEnum) {
    switch (weekEnum) {
        case MON:
            System.out.println("今天是工作日-8:30-5:30");
            break;
        case TUE:
            System.out.println("今天是工作日-8:30-5:30");
            break;
        case WEB:
            System.out.println("今天是工作日-8:30-5:30");
            break;
        case THUR:
            System.out.println("今天是工作日-8:30-5:30");
            break;
        case FRI:
            System.out.println("今天是工作日-8:30-5:30");
            break;
        default:
            System.out.println("休息");
    }
}

可读性得到了提高,如果你看到代码里面有人写:case 1这种代码,请提醒他可以使用枚举增加可读性.

使用抽象方法为每个枚举指定特定的行为

枚举不仅可以用来表示常量,有些时候,我们也可以将一些简单的计算逻辑写在枚举类中。这个时候,可以使用抽象方法来定义每个枚举需要实现的行为.

代码语言:txt
复制
package com.tea.modules.java8.enums;
代码语言:txt
复制
import lombok.Getter;
代码语言:txt
复制
/**
代码语言:txt
复制
 * com.tea.modules.java8.enums <br>
 * 运算符枚举
 *
 * @author jaymin
 * @since 2021/6/10
 */
@Getter
public enum OperationEnum {
    /**
     * 加
     */
    PLUS("+") {
        @Override
        public double apply(double x, double y) {
            return x + y;
        }
    },
    /**
     * 减
     */
    MINUS("-") {
        @Override
        public double apply(double x, double y) {
            return x - y;
        }
    },
    /**
     * 乘
     */
    TIMES("*") {
        @Override
        public double apply(double x, double y) {
            return x * y;
        }
    },
    /**
     * 除
     */
    DIVIDE("/") {
        @Override
        public double apply(double x, double y) {
            return x / y;
        }
    };
代码语言:txt
复制
    /**
代码语言:txt
复制
     * 运算符
     */
    private final String symbol;
代码语言:txt
复制
    OperationEnum(String symbol) {
代码语言:txt
复制
        this.symbol = symbol;
代码语言:txt
复制
    }
代码语言:txt
复制
    public abstract double apply(double x, double y);
代码语言:txt
复制
}

接口与枚举类

枚举类是final类,不支持继承关系。这个可以从反编译的文件中查看:

反编译

可以通过接口来让枚举实现一些通用的方法

  • 定义一个接口,声明打印名字的能力
代码语言:txt
复制
package com.tea.modules.java8.enums;
代码语言:txt
复制
/**
代码语言:txt
复制
 * com.tea.modules.java8.enums
 * 枚举接口
 * @author jaymin
 * @since 2021/6/17
 */
public interface EnumInfoService {
    /**
     * 打印枚举的名字
     */
    void printName();
}
  • 枚举类实现接口
代码语言:txt
复制
package com.tea.modules.java8.enums;
代码语言:txt
复制
/**
代码语言:txt
复制
 * com.tea.modules.java8.enums <br>
 * 使用枚举类来表示星期
 *
 * @author jaymin
 * @since 2021/6/9
 */
public enum WeekEnum implements EnumInfoService{
    /**
     * 周一
     */
    MON,
    /**
     * 周二
     */
    TUE,
    /**
     * 周三
     */
    WEB,
    /**
     * 周四
     */
    THUR,
    /**
     * 周五
     */
    FRI,
    /**
     * 周六
     */
    SAT,
    /**
     * 周日
     */
    SUN;
代码语言:txt
复制
    @Override
代码语言:txt
复制
    public void printName() {
代码语言:txt
复制
        System.out.println(this.name());
代码语言:txt
复制
    }
代码语言:txt
复制
}
  • Demo
代码语言:txt
复制
/**
代码语言:txt
复制
 * 枚举与接口
 */
private static void printEnumInfo(){
    EnumInfoService web = WeekEnum.WEB;
    web.printName();
}
public static void main(String[] args) {
    printEnumInfo();
}
  • Result
代码语言:txt
复制
WEB

EnumSet

EnumSet可以存储一个枚举中的元素,它提供了一种以集合的方式去操作枚举类的途径。

  • enumSet
代码语言:txt
复制
    /**
代码语言:txt
复制
     * EnumSet 的设计充分考虑到了速度因素,因为它必须与非常高效的 bit 标志相竞争(其操作与 HashSet 相比,非常地快).<br>
     * 就其内部而言,它(可能)就是将一个 long 值作为比特向量,所以 EnumSet 非常快速高效。<br>
     * 使用 EnumSet 的优点是,它在说明一个二进制位是否存在时,具有更好的表达能力,并且无需担心性能。
     */
    private static void enumSet() {
        // 空构造器
        EnumSet<WeekEnum> weekEnums = EnumSet.noneOf(WeekEnum.class);
        weekEnums.add(WeekEnum.MON);
        weekEnums.add(WeekEnum.TUE);
        weekEnums.add(WeekEnum.WEB);
        // of工厂,可以接收多个enum
        weekEnums.addAll(EnumSet.of(WeekEnum.THUR, WeekEnum.FRI, WeekEnum.SAT, WeekEnum.SUN));
        System.out.println(weekEnums);
        // range-范围
        weekEnums.removeAll(EnumSet.range(WeekEnum.MON, WeekEnum.WEB));
        System.out.println(weekEnums);
        // 创建一个与指定枚举集具有相同元素类型的枚举集,最初包含指定集中未包含的所有此类型的元素。
        weekEnums = EnumSet.complementOf(weekEnums);
        System.out.println(weekEnums);
    }
  • Result
代码语言:txt
复制
[MON, TUE, WEB, THUR, FRI, SAT, SUN]
代码语言:txt
复制
[THUR, FRI, SAT, SUN]
代码语言:txt
复制
[MON, TUE, WEB]

EnumMap

EnumMap可以以枚举作为Key,提供一种更快的速度来访问Map.

  • enumMap
代码语言:txt
复制
    /**
代码语言:txt
复制
     * EnumMap 是一种特殊的 Map,它要求其中的键(key)必须来自一个 enum,<br>
     * 由于 enum 本身的限制,所以 EnumMap 在内部可由数组实现。<br>
     * 因此 EnumMap 的速度很快,我们可以放心地使用 enum 实例在 EnumMap 中进行查找操作。<br>
     * 不过,我们只能将 enum 的实例作为键来调用 put() 可方法,其他操作与使用一般的 Map 差不多。<br>
     * 这里我们的例子是使用EnumMap来实现一个简单的命令模式
     */
    private static void enumMap() {
        EnumMap<WeekEnum, CommandService> commandServiceEnumMap = new EnumMap<>(WeekEnum.class);
        commandServiceEnumMap.put(WeekEnum.MON, () -> System.out.println("周一白酒涨停"));
        commandServiceEnumMap.put(WeekEnum.TUE, () -> System.out.println("周二有色跌停"));
        commandServiceEnumMap.put(WeekEnum.WEB, () -> System.out.println("周三大盘震荡"));
        for (Map.Entry<WeekEnum, CommandService> weekEnumCommandService : commandServiceEnumMap.entrySet()) {
            WeekEnum week = weekEnumCommandService.getKey();
            System.out.println(week.name() + "的策略:");
            weekEnumCommandService.getValue().action();
        }
    }
  • Result
代码语言:txt
复制
MON的策略:
代码语言:txt
复制
周一白酒涨停
代码语言:txt
复制
TUE的策略:
代码语言:txt
复制
周二有色跌停
代码语言:txt
复制
WEB的策略:
代码语言:txt
复制
周三大盘震荡

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
作者已关闭评论
0 条评论
热度
最新
推荐阅读
目录
  • 枚举可以做什么
  • 枚举类基础用法
    • API Document
    • switch配合枚举类编写状态机
    • 使用抽象方法为每个枚举指定特定的行为
    • 接口与枚举类
    • EnumSet
    • EnumMap
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档