java查询枚举_查找Java枚举的最佳实践
查找Java枚举的最佳实践
我们有一个REST API,客户端可以在其中提供表示Java Enums中服务器上定义的值的参数。
因此,我们可以提供一个描述性错误,我们将此valueOf(..)方法添加到每个Enum中。 似乎我们只是在复制代码(错误)。 有更好的做法吗?
public enum MyEnum {
A, B, C, D;
public static MyEnum lookup(String id) {
try {
return MyEnum.valueOf(id);
} catch (IllegalArgumentException e) {
throw new RuntimeException("Invalid value for my enum blah blah: " + id);
}
}
}
更新:valueOf(..)提供的默认错误消息将是No enum const class a.b.c.MyEnum.BadValue。我想从API中提供一个更具描述性的错误。
Marcus Leon asked 2020-08-02T10:08:59Z
10个解决方案
34 votes
可能可以实现通用的静态lookup方法。
像这样
public class LookupUtil {
public static > E lookup(Class e, String id) {
try {
E result = Enum.valueOf(e, id);
} catch (IllegalArgumentException e) {
// log error or something here
throw new RuntimeException(
"Invalid value for enum " + e.getSimpleName() + ": " + id);
}
return result;
}
}
那么你就可以
public enum MyEnum {
static public MyEnum lookup(String id) {
return LookupUtil.lookup(MyEnum.class, id);
}
}
或显式调用实用程序类查找方法。
Mykola Golubyev answered 2020-08-02T10:09:21Z
13 votes
看来您在这里有不好的作法,但在想不到的地方却没有。
捕获一个IllegalArgumentException以更清晰的消息重新抛出另一个RuntimeException,这似乎是个好主意,但事实并非如此。 因为这意味着您关心异常中的消息。
如果您关心异常中的消息,则意味着您的用户以某种方式看到了异常。 这不好。
如果要向用户提供显式错误消息,则应在解析用户输入时检查枚举值的有效性,如果用户输入不正确,则在响应中发送适当的错误消息。
就像是:
// This code uses pure fantasy, you are warned!
class MyApi
{
// Return the 24-hour from a 12-hour and AM/PM
void getHour24(Request request, Response response)
{
// validate user input
int nTime12 = 1;
try
{
nTime12 = Integer.parseInt(request.getParam("hour12"));
if( nTime12 <= 0 || nTime12 > 12 )
{
throw new NumberFormatException();
}
}
catch( NumberFormatException e )
{
response.setCode(400); // Bad request
response.setContent("time12 must be an integer between 1 and 12");
return;
}
AMPM pm = null;
try
{
pm = AMPM.lookup(request.getParam("pm"));
}
catch( IllegalArgumentException e )
{
response.setCode(400); // Bad request
response.setContent("pm must be one of " + AMPM.values());
return;
}
response.setCode(200);
switch( pm )
{
case AM:
response.setContent(nTime12);
break;
case PM:
response.setContent(nTime12 + 12);
break;
}
return;
}
}
Vincent Robert answered 2020-08-02T10:09:59Z
3 votes
为什么我们必须编写那5行代码?
public class EnumTest {
public enum MyEnum {
A, B, C, D;
}
@Test
public void test() throws Exception {
MyEnum.valueOf("A"); //gives you A
//this throws ILlegalargument without having to do any lookup
MyEnum.valueOf("RADD");
}
}
Kannan Ekanath answered 2020-08-02T10:10:19Z
3 votes
如果您希望查找不区分大小写,则可以遍历所有值,使其更加友好:
public enum MyEnum {
A, B, C, D;
public static MyEnum lookup(String id) {
boolean found = false;
for(MyEnum enum: values()){
if(enum.toString().equalsIgnoreCase(id)) found = true;
}
if(!found) throw new RuntimeException("Invalid value for my enum: " +id);
}
}
Adam answered 2020-08-02T10:10:39Z
3 votes
Guava还提供了这样的功能,如果找不到枚举,它将返回Optional。
Enums.getIfPresent(MyEnum.class, id).toJavaUtil()
.orElseThrow(()-> new RuntimeException("Invalid enum blah blah blah.....")))
Ken Chan answered 2020-08-02T10:10:59Z
2 votes
IllegalArgumentException中的错误消息已经足够描述。
您的方法会在特定消息中产生一般性异常,只需将其改写为相同的消息即可。 开发人员更喜欢特定的异常类型,并且可以适当地处理这种情况,而不必尝试处理RuntimeException。
如果要使消息更加用户友好,则对枚举值的引用无论如何都与它们无关。 让UI代码确定应向用户显示的内容,并且UI开发人员最好使用IllegalArgumentException。
Robin answered 2020-08-02T10:11:28Z
2 votes
更新:正如GreenTurtle正确指出的那样,以下错误
我只会写
boolean result = Arrays.asList(FooEnum.values()).contains("Foo");
这可能比捕获运行时异常的性能要差,但是可以使代码更简洁。 捕获此类异常始终是一个坏主意,因为它容易出错。当检索比较值本身导致IllegalArgumentException时会发生什么? 然后将其视为枚举器的不匹配值。
makrom answered 2020-08-02T10:11:57Z
2 votes
对于Rest / Json等,我们会像这样进行所有枚举。它的优点是该错误是人类可读的,并且还提供了可接受的值列表。 我们使用的是自定义方法MyEnum.fromString而不是MyEnum.valueOf,希望对您有所帮助。
public enum MyEnum {
A, B, C, D;
private static final Map NAME_MAP = Stream.of(values())
.collect(Collectors.toMap(MyEnum::toString, Function.identity()));
public static MyEnum fromString(final String name) {
MyEnum myEnum = NAME_MAP.get(name);
if (null == myEnum) {
throw new IllegalArgumentException(String.format("'%s' has no corresponding value. Accepted values: %s", name, Arrays.asList(values())));
}
return myEnum;
}
}
例如,如果您致电
MyEnum value = MyEnum.fromString("X");
您将收到带有以下消息的IllegalArgumentException:
“ X”没有相应的值。 接受的值:[A,B,C,D]
您可以将IllegalArgumentException更改为自定义对象。
Radu Sebastian LAZIN answered 2020-08-02T10:12:35Z
0 votes
您可以使用静态查找映射来避免该异常并返回null,然后根据需要抛出:
public enum Mammal {
COW,
MOUSE,
OPOSSUM;
private static Map lookup =
Arrays.stream(values())
.collect(Collectors.toMap(Enum::name, Function.identity()));
public static Mammal getByName(String name) {
return lookup.get(name);
}
}
mskfisher answered 2020-08-02T10:12:55Z
0 votes
Apache Commons Lang 3包含EnumUtils类。 如果您没有在项目中使用Apache Commons,那么您做错了。 您正在重新发明轮子!
我们可以使用很多很酷的方法而不会引发异常。 例如:
获取该类的枚举,如果找不到,则返回null。
此方法与Enum.valueOf的不同之处在于它不会抛出 无效的枚举名称,并且不区分大小写 名称的匹配。
EnumUtils.getEnumIgnoreCase(SeasonEnum.class, season);
Willian Crozeta answered 2020-08-02T10:13:28Z
java查询枚举_查找Java枚举的最佳实践相关推荐
- java查询序列_基于JAVA的苹果序列号查询api调用代码实例
代码描述:基于JAVA的苹果序列号查询api调用代码实例 关联数据:苹果序列号 接口地址:http://www.juhe.cn/docs/api/id/37 1.[代码][Java]代码 import ...
- java 中的枚举_说说Java中的枚举(一)
在实际编程中,往往存在着这样的"数据集",它们的数值在程序中是稳定的,而且"数据集"中的元素是有限的.例如星期一到星期日七个数据元素组成了一周的"数据 ...
- java enum int 转换为枚举_关于java:从枚举序号转换为枚举类型
我有一个枚举类型ReportTypeEnum,它在所有类的方法之间传递,但是我需要在URL上传递它,所以我使用序数方法来获取int值.在我把它放到我的另一个JSP页面之后,我需要将它转换回一个Repo ...
- java什么是枚举_【JAVA】浅谈java枚举类
一.什么情况下使用枚举类? 有的时候一个类的对象是有限且固定的,这种情况下我们使用枚举类就比较方便? 二.为什么不用静态常量来替代枚举类呢? public static final int SEASO ...
- java正则表达式 匹配()_学习Java正则表达式(匹配、替换、查找)
import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; public c ...
- c++ main函数调用 类中的枚举_为啥用枚举,枚举有哪些用法?
Java基础:枚举的用法与原理 在学习过程中,我们也只是在定义常量的时候,会意识到枚举的存在,而定义常量其实可以在类中实现,这时就会感觉枚举有点鸡肋.但在实际项目开发的过程中,枚举因相当迷人的特性而受 ...
- java核心教程_核心Java教程
java核心教程 Welcome to Core Java Tutorial. I have written a lot on Core Java and Java EE frameworks. Th ...
- java初始化数据报_初始化java原因
虚拟机的类加载机制 虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Java类 即虚拟机的类加载机制. 在Java中,类型的加载.链接 ...
- java 流程控制_《Java基础知识》Java流程控制
流程控制分类: 一.顺序结构 如果没有流程控制(即没有分支结构和循环结构),Java方法里面的语句是一个顺序执行流,从上到下依次执行每条语句. 二.分支结构 1.if语句 if语句使用布尔表达式或者布 ...
最新文章
- 使用liner、feather、multiband对已经拼接的数据进行融合(下)
- 如何做EL表达式能调用的函数-小例子(转)
- UVA11078开放式学分制(前面-后面的最大值)
- 修改默认runlevel
- Android GridView的使用方法
- VMware Device/Credential Guard 不兼容
- PageCollectionView[Bug],使用Filter的时候,删除集合中的元素,会导致ArgumentOutOfRangeException...
- 【最全资料下载】Kubernetes and Cloud Native Meetup (北京站)
- mysql存储java对象_Mysql存储java对象 | 学步园
- [Contest20180116]随机游走
- SOME/IP不等同于SOA,CommonAPI-RPC通信和vsomeip基于消息通信
- deepin 惠普打印驱动安装
- 【数理统计】02. 抽样分布与次序统计量
- lpx寒假作业案例14
- 关于求职及面试的一些小技巧
- Esxi通过U盘启动
- No Matter What
- 三菱PLC编程与案例精讲之ST语言
- GPT-2 论文翻译
- 利用BibTeX批量导入参考文献
热门文章
- span文字强制换行
- 跨境电商“三分天下”格局已定,洋码头再融资也难当“领头羊”?
- win10占用内存过高的解决办法
- python openpyxl详解_python openpyxl使用方法详解
- 购买单反相机的注意事项(转载)
- 国内外各类信息安全和网络对抗竞赛介绍
- 获取textview行数
- kernel(三)NAND FLASH
- Ignored attempt to cancel a touchmove event with cancelable=false
- python实现滑动验证码_使用python实现滑动验证码