我的代码中有多个枚举:
public enum First { a, b, c, d; }
public enum Second { e, f, g; }
我想有一个方法,使用valueOf()检查任何枚举中是否存在值,而不为每个枚举类型写一个值。例如(此代码不运行):
public boolean enumTypeContains(Enum e, String s) {
try {
e.valueOf(s);
} catch (IllegalArgumentException iae) {
return false;
}
return true;
}
用法:
enumTypeContains(First,"a"); // returns true
enumTypeContains(Second,"b"); // returns false
关于如何做这样的事情的任何想法?
答案 0 :(得分:10)
这应该有效:
public <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) {
try {
Enum.valueOf(e, s);
return true;
}
catch(IllegalArgumentException ex) {
return false;
}
}
然后你必须通过
来调用它enumTypeContains(First.class, "a");
我不确定是否只是简单地搜索这些值(比如来自jinguy的答案)可能比创建和抛出异常更快。这将取决于您获得false
的频率,您拥有的常数以及堆栈跟踪的持续时间(例如,调用的深度)。
如果您经常需要(对于相同的枚举),最好创建一次HashSet或HashMap将名称映射到枚举值。
答案 1 :(得分:8)
以下是您的解决方案:
public static boolean contains(Class<? extends Enum> clazz, String val) {
Object[] arr = clazz.getEnumConstants();
for (Object e : arr) {
if (((Enum) e).name().equals(val)) {
return true;
}
}
return false;
}
它获取所有enum的vaules并检查它是否具有与您传入的参数共享名称的值。如果是,则返回true,否则返回false。
这已经过测试并且有效。测试代码:
public class Test {
public static void main(String[] args) {
System.out.println(contains(Haha.class, "Bad"));
System.out.println(contains(Haha.class, "Happy"));
System.out.println(contains(Haha.class, "Sad"));
}
static enum Haha {
Happy, Sad;
}
}
打印:
false
true
true
答案 2 :(得分:3)
我找到了另一个变体,既不迭代所有枚举常量也不抛出异常......但它是特定于实现的,即使用未记录的方法。它适用于Sun的JDK 1.6.0_20(并且是通过阅读1.6.0_13中的源代码制作的。)
public static <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) {
try {
Method enumDir = Class.class.getDeclaredMethod("enumConstantDirectory");
enumDir.setAccessible(true);
Map<?,?> dir = (Map<?,?>)enumDir.invoke(e);
return dir.containsKey(s);
}
catch(NoSuchMethodException ex) {
throw new Error(ex);
}
catch(IllegalAccessException ex) {
throw new Error(ex);
}
catch(InvocationTargetException ex) {
throw new Error(ex.getCause());
}
}
如果我们在java.lang
包中,这可能看起来像这样:
public static <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) {
return e.enumConstantDirectory().containsKey(s);
}
这使用方法Class.enumConstantDirectory()
,它(在第一次调用时)创建并且(稍后仅)返回一个包含所有枚举常量作为值的映射,它们的名称作为键。 (只有这样的地图也可以手动创建。)
此方法由Enum.valueOf(Class, String)
在内部使用,也可能由EnumType.valueOf(String)
使用(取决于编译器)。
在enumConstantDirectory
或getEnumConstants()
的第一次调用中,私有帮助器方法调用EnumType.values()
(由编译器实现)。然后将结果重用于以下两种方法的调用。