1. 概述
在这篇短文中,我们将深入探讨“IllegalArgumentException: No enum const class" 异常。
首先,我们将理解这种异常背后的原因。接着,通过一个实际例子来重现它,最后学习如何修复它。
2. 原因
在深入了解之前,我们先理解这个异常及其堆栈跟踪的含义。
通常情况下,当我们将非法或不合适的值传递给方法时,会抛出 IllegalArgumentException。
“No enum const class" 提示我们在指定的枚举类型中没有找到具有给定名称的常量。
所以,这种异常最常见的原因是通常使用无效的枚举常量作为方法参数。
3. 重现异常
现在我们知道异常的含义了,让我们通过一个实际例子来重现它。
例如,考虑 Priority 枚举:
public enum Priority {
HIGH("High"), MEDIUM("Medium"), LOW("Low");
private String name;
Priority(String name) {
this.name = name;
}
public String getPriorityName() {
return name;
}
}
如图所示,我们的枚举有一个私有字段 name,表示每个 Priority 常量的名称。
接下来,我们创建一个静态方法来通过名称获取一个 Priority 常量:
public class PriorityUtils {
public static Priority getByName(String name) {
return Priority.valueOf(name);
}
public static void main(String[] args) {
System.out.println(getByName("Low"));
}
}
现在如果我们执行 PriorityUtils 类,就会得到一个异常:
Exception in thread "main" java.lang.IllegalArgumentException: No enum constant com.baeldung.exception.noenumconst.Priority.Low
at java.lang.Enum.valueOf(Enum.java:238)
at com.baeldung.exception.noenumconst.Priority.valueOf(Priority.java:1)
....
查看堆栈跟踪,getByName(String name)
方法由于内置方法 Enum.valueOf(Class<T>, String)
未能找到名称为“Low" 的 Priority 常量而失败。
Enum.valueOf()
方法只接受必须与枚举中声明常量标识符完全匹配的字符串。换句话说,它只接受 HIGH、MEDIUM 和 LOW 作为参数。由于它不知道 name 属性,当我们传入值“Low” 时,它会抛出 IllegalArgumentException。
现在,让我们用测试案例来验证这一点:
@Test
void givenCustomName_whenUsingGetByName_thenThrowIllegalArgumentException() {
assertThrows(IllegalArgumentException.class, () -> PriorityUtils.getByName("Low"));
}
4. 解决方案
最简单的解决方案是在将自定义的 name 传递给 Enum.valueOf()
方法之前,先将其转换为大写。这样可以确保传递的字符串与常量名称完全匹配,这些名称都是大写的。
现在,让我们看看它是如何工作的:
public static Priority getByUpperCaseName(String name) {
if (name == null || name.isEmpty()) {
return null;
}
return Priority.valueOf(name.toUpperCase());
}
为了防止任何 NullPointerException 或意外行为,我们添加了一个检查,确保给定的名称不为 null 并且不为空。
最后,我们添加一些测试用例以确认一切都按预期工作:
@Test
void givenCustomName_whenUsingGetByUpperCaseName_thenReturnEnumConstant() {
assertEquals(Priority.HIGH, PriorityUtils.getByUpperCaseName("High"));
}
正如我们所见,我们成功地使用自定义名称 High 获取到了 Priority.HIGH。
现在,让我们看看当我们传递 null 或空值时会发生什么:
@Test
void givenEmptyName_whenUsingGetByUpperCaseName_thenReturnNull() {
assertNull(PriorityUtils.getByUpperCaseName(""));
}
@Test
void givenNull_whenUsingGetByUpperCaseName_thenReturnNull() {
assertNull(PriorityUtils.getByUpperCaseName(null));
}
如上所述,方法确实返回了 null。
5. 总结
在这篇简短教程中,我们详细讨论了Java为何抛出“IllegalArgumentException: No enum const class" 异常的原因。
途中,我们学会了如何产生这个异常,并通过实际例子学习了如何修复它。
如往常一样,所有示例的完整源代码可在GitHub 上找到。