java 检查枚举类型是否包含具有给定名称的常量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6850638/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Checking if enum type contains constant with given name
提问by BugsPray
I have multiple enums in my code:
我的代码中有多个枚举:
public enum First { a, b, c, d; }
public enum Second { e, f, g; }
I want to have one method that checks to see if a value is present in any enum using valueOf() without writing one for each enum type. For example (this code does not run):
我想要一种方法来检查使用 valueOf() 的任何枚举中是否存在一个值,而不用为每个枚举类型编写一个。例如(此代码不运行):
public boolean enumTypeContains(Enum e, String s) {
try {
e.valueOf(s);
} catch (IllegalArgumentException iae) {
return false;
}
return true;
}
Usage:
用法:
enumTypeContains(First,"a"); // returns true
enumTypeContains(Second,"b"); // returns false
Any ideas on how to do something like this?
关于如何做这样的事情的任何想法?
回答by Pa?lo Ebermann
This should work:
这应该有效:
public <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) {
try {
Enum.valueOf(e, s);
return true;
}
catch(IllegalArgumentException ex) {
return false;
}
}
You then have to call it by
然后你必须通过调用它
enumTypeContains(First.class, "a");
I'm not sure if simply searching through the values (like in the answer from jinguy) might be faster than creating and throwing an exception, though. This will depend on how often you will get false
, how many constants you have, and how long the stack trace is (e.g. how deep this is called).
不过,我不确定简单地搜索值(如 jinguy 的答案)是否可能比创建和抛出异常更快。这将取决于您获得 的频率false
、您拥有的常量数量以及堆栈跟踪的长度(例如调用的深度)。
If you need this often (for the same enum), it might be better to create once a HashSet or a HashMap mapping the names to the enum values.
如果您经常需要这样做(对于同一个枚举),最好创建一次 HashSet 或 HashMap 将名称映射到枚举值。
回答by jjnguy
Here is your solution:
这是您的解决方案:
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;
}
It gets all of the enum's vaules and checks to see if it has a value that shares a name with the parameter you passed in. If so, then it returns true, otherwise it returns false.
它获取枚举的所有值并检查它是否具有与您传入的参数共享名称的值。如果是,则返回 true,否则返回 false。
This has been tested and works. Test code:
这已经过测试并且有效。测试代码:
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;
}
}
Prints:
印刷:
false
true
true
回答by Pa?lo Ebermann
I found another variant which has neither to iterate all enum constants nor to throw an exception ... but it is implementation specific, i.e. uses undocumented methods. It works for Sun's JDK 1.6.0_20 (and was made by reading the source code from 1.6.0_13).
我发现了另一个变体,它既不需要迭代所有枚举常量,也不需要抛出异常……但它是特定于实现的,即使用未记录的方法。它适用于 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());
}
}
If we were in the java.lang
package, this could simply look like this:
如果我们在java.lang
包中,这可能看起来像这样:
public static <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) {
return e.enumConstantDirectory().containsKey(s);
}
This uses the method Class.enumConstantDirectory()
, which (on first call) creates and (later only) returns a map with all the enum constants as values, their names as key. (Just such a map one could also create manually.)
这使用方法Class.enumConstantDirectory()
,该方法(在第一次调用时)创建并(仅稍后)返回一个映射,其中所有枚举常量作为值,它们的名称作为键。(也可以手动创建这样的地图。)
This method is used internally by Enum.valueOf(Class, String)
, and supposedly also by EnumType.valueOf(String)
(depends on compiler).
此方法由 内部使用Enum.valueOf(Class, String)
,据说也由EnumType.valueOf(String)
(取决于编译器)使用。
On the first call of enumConstantDirectory
or getEnumConstants()
, a private helper method invokes EnumType.values()
(which is implemented by the compiler). The result is then reused for following calls of these two methods.
在第一次调用enumConstantDirectory
or 时getEnumConstants()
,会调用私有辅助方法EnumType.values()
(由编译器实现)。然后将结果重用于这两个方法的后续调用。