写点什么

枚举代替常量

作者:李子捌
  • 2021 年 12 月 21 日
  • 本文字数:2535 字

    阅读完需:约 8 分钟

枚举代替常量

1、简介

不知道大家有没有在自己项目中看到过类似下面这样的代码:


public static void fruitsHandle(String fruits) {
switch (fruits) { case "Apple": // TODO break; case "Banana": // TODO break; case "Orange": // TODO break; default: throw new IllegalStateException("Unexpected value: " + fruits); }
}
复制代码


出现上面这种情况是非常少的,小萌新一般也不会直接在方法中重复定义字符串进行比较,而会将其定义为常量,或者统一抽取为常量类。所以一般会看到这种代码(小捌经常在项目中看到类似这样的代码,但是小捌不敢吭声😄😄):


private static final String APPLE = "Apple";private static final String BANANA = "Banana";private static final String ORANGE = "Orange";
public static void fruitsHandle(String fruits) {
switch (fruits) { case APPLE: // TODO break; case BANANA: // TODO break; case ORANGE: // TODO break; default: throw new IllegalStateException("Unexpected value: " + fruits); }
}
复制代码


上面这种情况我们在代码中出现的频率非常高;它需要程序员提供一组固定常量,并且这一组固定常量在开发时或者说编译时就知道了具体的成员,这个时候我们就应该使用枚举。


枚举类型(enum type)是指由一组固定常量组成合法值的类型。


2、优势

使用枚举类型,相比直接定义常量能够带来非常多的好处。​

2.1 类型安全

分别定义一个简单的肉类枚举和水果枚举


// 肉类枚举public enum MeetEnums {
BEEF, PORK, FISH;
}
复制代码


// 水果枚举public enum FruitsEnums {
APPLE, BANANA, ORANGE;
}
复制代码


我们改造上面的代码,修改入参类型即可


public static void fruitsHandle(FruitsEnums fruits) {
switch (fruits) { case APPLE: // TODO break; case BANANA: // TODO break; case ORANGE: // TODO break; default: throw new IllegalStateException("Unexpected value: " + fruits); }
}
复制代码


可以看到定义枚举类型带来函数类型安全性,如果定义的是常量则无法代理这种效果


2.2 枚举能够提供更多信息

枚举在本质上还是一个类,它能够定义属性和方法,我们可以在枚举类中定义想要的方法、或者通过属性扩展枚举提供的基础信息。比如我们做 web 开发时最常见的 HttpStatus,在 springframework 框架中就被定义成了枚举类,它不仅包含了 Http 响应码,还能包含描述状态。


public enum HttpStatus {
OK(200, "OK"), NOT_FOUND(404, "Not Found"), INTERNAL_SERVER_ERROR(500, "Internal Server Error"); private final int value; private final String reasonPhrase;
private HttpStatus(int value, String reasonPhrase) { this.value = value; this.reasonPhrase = reasonPhrase; } }
复制代码

2.3 通过函数提供更多服务

此外 HttpStatus 它内部还嵌套了 Series 枚举类,这个类可以协助 HttpStatus 枚举类,通过 statusCode / 100 的模判断当前的枚举状态是 is1xxInformational、is2xxSuccessful、is3xxRedirection、is4xxClientError、is5xxServerError 等等。


public static enum Series {        INFORMATIONAL(1),        SUCCESSFUL(2),        REDIRECTION(3),        CLIENT_ERROR(4),        SERVER_ERROR(5);
private final int value;
private Series(int value) { this.value = value; }
public int value() { return this.value; }
public static HttpStatus.Series valueOf(HttpStatus status) { return valueOf(status.value); }
public static HttpStatus.Series valueOf(int statusCode) { HttpStatus.Series series = resolve(statusCode); if (series == null) { throw new IllegalArgumentException("No matching constant for [" + statusCode + "]"); } else { return series; } }
@Nullable public static HttpStatus.Series resolve(int statusCode) { int seriesCode = statusCode / 100; HttpStatus.Series[] var2 = values(); int var3 = var2.length;
for(int var4 = 0; var4 < var3; ++var4) { HttpStatus.Series series = var2[var4]; if (series.value == seriesCode) { return series; } }
return null; } }
复制代码

2.4 获取所有定义的类型

所有的枚举类会自动产生一个_values_()方法,它能返回当前定义枚举类的数组集,因此可以很方便的遍历怎么枚举类定义的所有枚举。比如我们简单改造一下 MeetEnums 枚举类:


public enum MeetEnums {
BEEF("牛肉"), PORK("猪肉"), FISH("鱼肉");
String name;
public String getName() { return name; }
MeetEnums(String name) { this.name = name; }
public static MeetEnums getMeetEnumsByName(String name) { MeetEnums[] values = values(); Optional<MeetEnums> optional = Stream.of(values).filter(v -> v.getName().equals(name)).findAny(); return optional.isPresent() ? optional.get() : null; }
}
复制代码


总之枚举类相比常量来说有太多的优点,它能使得代码更加整洁美观、安全性强、功能强大。虽然大部分情况下,枚举类的选择是由于常量定义的,但是也并不是任何时候都一定要把常量定义成枚举;具体情况大家就可以自己去斟酌啦!

发布于: 2 小时前阅读数: 4
用户头像

李子捌

关注

华为云享专家 2020.07.20 加入

公众号【李子捌】

评论

发布
暂无评论
枚举代替常量