注册

还在频繁定义常量?不试试用枚举代替

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;
}

}

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


作者:李子捌
链接:https://juejin.cn/post/7025394182210453540
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

0 个评论

要回复文章请先登录注册