我们有一个REST API,客户端可以在Java Enums中提供表示服务器上定义的值的参数.
因此我们可以提供描述性错误,我们将此lookup方法添加到每个枚举.好像我们只是在复制代码(坏).有更好的做法吗?
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
更新:提供的默认错误消息valueOf(..)是No enum const class a.b.c.MyEnum.BadValue.我想从API中提供更具描述性的错误.
Myk*_*yev 34
可能你可以实现通用的静态lookup方法.
像这样
public class LookupUtil {
public static <E extends Enum<E>> E lookup(Class<E> 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;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以
public enum MyEnum {
static public MyEnum lookup(String id) {
return LookupUtil.lookup(MyEnum.class, id);
}
}
Run Code Online (Sandbox Code Playgroud)
或者显式调用实用程序类查找方法.
Vin*_*ert 13
看起来你在这里做的不好,但不是你想的.
抓住一个用更清晰的信息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;
}
}
Run Code Online (Sandbox Code Playgroud)
当涉及到 Rest/Json 等时,我们像这样执行所有枚举。 它的优点是错误是人类可读的,并且还为您提供了可接受的值列表。我们正在使用自定义方法 MyEnum.fromString 而不是 MyEnum.valueOf,希望它有所帮助。
public enum MyEnum {
A, B, C, D;
private static final Map<String, MyEnum> 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;
}
}
Run Code Online (Sandbox Code Playgroud)
所以例如如果你打电话
MyEnum value = MyEnum.fromString("X");
Run Code Online (Sandbox Code Playgroud)
您将收到带有以下消息的 IllegalArgumentException:
'X' 没有对应的值。接受值:[A、B、C、D]
您可以将 IllegalArgumentException 更改为自定义异常。
Guava 还提供了这样的函数,Optional如果找不到枚举,它将返回一个。
Enums.getIfPresent(MyEnum.class, id).toJavaUtil()
.orElseThrow(()-> new RuntimeException("Invalid enum blah blah blah.....")))
Run Code Online (Sandbox Code Playgroud)
Apache Commons Lang 3 包含 EnumUtils 类。如果您没有在项目中使用 Apache Commons,那么您就做错了。你正在重新发明轮子!
我们可以使用许多很酷的方法而不会引发异常。例如:
获取类的枚举,如果未找到则返回 null。
此方法与 Enum.valueOf 的不同之处在于,它不会针对无效的枚举名称引发异常,并执行名称的不区分大小写的匹配。
EnumUtils.getEnumIgnoreCase(SeasonEnum.class, season);
Run Code Online (Sandbox Code Playgroud)
如果您希望查找不区分大小写,您可以循环遍历这些值,使其更加友好:
public enum MyEnum {
A, B, C, D;
public static MyEnum lookup(final String id) {
for(MyEnum enumValue: values()){
if(enumValue.name().equalsIgnoreCase(id)){
return enumValue;
}
}
throw new RuntimeException("Invalid value for my enum: " + id);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
88855 次 |
| 最近记录: |