Checking if the enum type contains a constant with the given name

I have several listings in my code:

public enum First { a, b, c, d; } public enum Second { e, f, g; } 

I want to have one method that checks if a value is present in any enum using valueOf () without entering one for each type of enum. For example (this code does not run):

 public boolean enumTypeContains(Enum e, String s) { try { e.valueOf(s); } catch (IllegalArgumentException iae) { return false; } return true; } 

Using:

 enumTypeContains(First,"a"); // returns true enumTypeContains(Second,"b"); // returns false 

Any ideas on how to do something like this?

+7
source share
3 answers

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 the enum vaules and checks to see if the value has a value that has a name with the parameter in which you passed. If so, then it returns true, otherwise it returns 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; } } 

Print

 false true true 
+8
source

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; } } 

Then you have to call him

 enumTypeContains(First.class, "a"); 

I'm not sure that a simple value search (e.g. in response from jinguy) may be faster than throwing and throwing an exception. This will depend on how often you get false , how many constants you have and how long the stack trace is traced (for example, how deep it is called).

If you need this often (for the same enumeration), it would be better to create one time when a HashSet or HashMap matches names with enumeration values.

+10
source

I found another option that should neither rename all enumeration constants nor throw an exception ... but it is implementation-specific, i.e. uses undocumented methods. It works for Sun JDK 1.6.0_20 (and was made by reading the source code from 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 , it might look something like this:

 public static <E extends Enum<E>> boolean enumTypeContains(Class<E> e, String s) { return e.enumConstantDirectory().containsKey(s); } 

Here we use the Class.enumConstantDirectory() method, which (on the first call) creates and (later only) returns a map with all enumeration constants as values, their names as the key. (It is precisely such a map that can be created manually).

This method is used inside Enum.valueOf(Class, String) and supposedly also EnumType.valueOf(String) (depends on the compiler).

The first time enumConstantDirectory or getEnumConstants() is called, the private helper method calls EnumType.values() (which is implemented by the compiler). The result is then reused for the following calls to these two methods.

+3
source

All Articles