Buscar enum de Java por valor de cadena

Digamos que tengo una enumeración que es solo

public enum Blah { A, B, C, D } 

y me gustaría encontrar el valor enum de una cadena, por ejemplo, "A" que sería Blah.A ¿Cómo sería posible hacer esto?

¿Es el Enum.valueOf() el método que necesito? Si es así, ¿cómo usaría esto?

Sí, Blah.valueOf("A") te dará Blah.A

Tenga en cuenta que el nombre debe ser una coincidencia exacta , incluido el caso: Blah.valueOf("a") y Blah.valueOf("A ") arrojan una IllegalArgumentException .

Los métodos estáticos valueOf() y values() se crean en tiempo de comstackción y no aparecen en el código fuente. Sin embargo, aparecen en Javadoc; por ejemplo, Dialog.ModalityType muestra ambos métodos.

Otra solución si el texto no es el mismo que el valor de enumeración:

 public enum Blah { A("text1"), B("text2"), C("text3"), D("text4"); private String text; Blah(String text) { this.text = text; } public String getText() { return this.text; } public static Blah fromString(String text) { for (Blah b : Blah.values()) { if (b.text.equalsIgnoreCase(text)) { return b; } } return null; } } 

Aquí hay una utilidad ingeniosa que uso:

 /** * A common method for all enums since they can't have another base class * @param  Enum type * @param c enum type. All enums must be all caps. * @param string case insensitive * @return corresponding enum, or null */ public static > T getEnumFromString(Class c, String string) { if( c != null && string != null ) { try { return Enum.valueOf(c, string.trim().toUpperCase()); } catch(IllegalArgumentException ex) { } } return null; } 

Luego, en mi clase enum, generalmente tengo esto para guardar algo de tipeo:

 public static MyEnum fromString(String name) { return getEnumFromString(MyEnum.class, name); } 

Si sus enumeraciones no son mayúsculas, simplemente cambie la línea Enum.valueOf .

Lástima que no puedo usar T.class para Enum.valueOf cuando T se borra.

También debe tener cuidado con su caso. Déjame explicarte: hacer Blah.valueOf("A") funciona, pero Blah.valueOf("a") no funcionará. Entonces otra vez Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) funcionaría.

editar
Se cambió toUpperCase por toUpperCase(Locale.ENGLISH) función de tc. comentario y los documentos de Java

edit2 En Android debes usar Locale.US , como señala sulai .

Usa el patrón de Joshua Bloch, Effective Java :

(simplificado por brevedad)

 enum MyEnum { ENUM_1("A"), ENUM_2("B"); private String name; private static final Map ENUM_MAP; MyEnum (String name) { this.name = name; } public String getName() { return this.name; } // Build an immutable map of String name to enum pairs. // Any Map impl can be used. static { Map map = new ConcurrentHashMap(); for (MyEnum instance : MyEnum.values()) { map.put(instance.getName(),instance); } ENUM_MAP = Collections.unmodifiableMap(map); } public static MyEnum get (String name) { return ENUM_MAP.get(name); } } 

Ver también:

Oracle Java Example utilizando Enum y Map of instances

Orden de ejecución de bloques estáticos en un tipo Enum

¿Cómo puedo buscar una enumeración Java a partir de su valor de cadena?

Aquí hay un método que puede hacerlo para cualquier Enum, y no distingue entre mayúsculas y minúsculas.

 /** * Finds the value of the given enumeration by name, case-insensitive. * Throws an IllegalArgumentException if no match is found. **/ public static > T valueOfIgnoreCase( Class enumeration, String name) { for (T enumValue : enumeration.getEnumConstants()) { if (enumValue.name().equalsIgnoreCase(name)) { return enumValue; } } throw new IllegalArgumentException(String.format( "There is no value with name '%s' in Enum %s", name, enumeration.getName() )); } 

Usar Blah.valueOf(string) es lo mejor, pero también puedes usar Enum.valueOf(Blah.class, string) .

Si no desea escribir su propia utilidad, use la biblioteca de guayaba de Google:

 Enums.getIfPresent(Blah.class, "A") 

A diferencia de la función incorporada en java, te permite verificar si A está presente en Blah y no lanza una excepción.

Puede necesitar esto:

 public enum ObjectType { PERSON("Person"); public String parameterName; ObjectType(String parameterName) { this.parameterName = parameterName; } public String getParameterName() { return this.parameterName; } //From String method will return you the Enum for the provided input string public static ObjectType fromString(String parameterName) { if (parameterName != null) { for (ObjectType objType : ObjectType.values()) { if (parameterName.equalsIgnoreCase(objType.parameterName)) { return objType; } } } return null; } } 

Una más adición:

  public static String fromEnumName(String parameterName) { if (parameterName != null) { for (DQJ objType : DQJ.values()) { if (parameterName.equalsIgnoreCase(objType.name())) { return objType.parameterName; } } } return null; } 

Esto le devolverá el valor mediante un nombre de enumeración Stringified. Por ejemplo, si proporciona “PERSONA” en el nombre deEnEdición, le devolverá el valor de Enum, es decir, “Persona”.

En Java 8 o posterior, usando Streams :

 public enum Blah { A("text1"), B("text2"), C("text3"), D("text4"); private String text; Blah(String text) { this.text = text; } public String getText() { return this.text; } public static Blah fromText(String text) { return Arrays.stream(values()) .filter(bl -> bl.text.equalsIgnoreCase(text)) .findFirst() .orElse(null); } } 

Otra forma de hacerlo es usar el name() implícito del método estático name() de Enum. name devolverá la cadena exacta utilizada para crear esa enumeración que se puede usar para verificar contra la cadena proporcionada:

 public enum Blah { A, B, C, D; public static Blah getEnum(String s){ if(A.name().equals(s)){ return A; }else if(B.name().equals(s)){ return B; }else if(C.name().equals(s)){ return C; }else if (D.name().equals(s)){ return D; } throw new IllegalArgumentException("No Enum specified for this string"); } } 

Pruebas:

System.out.println(Blah.getEnum("B").name());

 //it will print BB 

inspiración: 10 ejemplos de Enum en Java

Mis 2 centavos aquí: usando Java8 Streams + verificando una cadena exacta:

 public enum MyEnum { VALUE_1("Super"), VALUE_2("Rainbow"), VALUE_3("Dash"), VALUE_3("Rocks"); private final String value; MyEnum(String value) { this.value = value; } /** * @return the Enum representation for the given string. * @throws IllegalArgumentException if unknown string. */ public static MyEnum fromString(String s) throws IllegalArgumentException { return Arrays.stream(MyEnum.values()) .filter(v -> v.value.equals(s)) .findFirst() .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s)); } } 

** EDIT **

fromString() el nombre de la función a fromString() ya que al nombrarla usando esa convención, obtendrá algunos beneficios del lenguaje Java; por ejemplo:

  1. Conversión directa de tipos en la anotación HeaderParam

Solución usando las bibliotecas de guayaba El método getPlanet () no distingue entre mayúsculas y minúsculas, por lo que getPlanet (“MerCUrY”) devolverá Planet.MERCURY.

 package com.universe.solarsystem.planets; import org.apache.commons.lang3.StringUtils; import com.google.common.base.Enums; import com.google.common.base.Optional; //Pluto and Eris are dwarf planets, who cares! public enum Planet { MERCURY, VENUS, EARTH, MARS, JUPITER, SATURN, URANUS, NEPTUNE; public static Planet getPlanet(String name) { String val = StringUtils.trimToEmpty(name).toUpperCase(); Optional  possible = Enums.getIfPresent(Planet.class, val); if (!possible.isPresent()) { throw new IllegalArgumentException(val + "? There is no such planet!"); } return possible.get(); } } 

Para agregar a las respuestas anteriores y abordar algunas de las discusiones sobre nulls y NPE, estoy usando Guava Optionals para manejar casos ausentes / inválidos. Esto funciona muy bien para URI / análisis de parámetros.

 public enum E { A,B,C; public static Optional fromString(String s) { try { return Optional.of(E.valueOf(s.toUpperCase())); } catch (IllegalArgumentException|NullPointerException e) { return Optional.absent(); } } } 

Para aquellos que no lo saben, aquí hay más información sobre cómo evitar el nulo con Opcional: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

 public static MyEnum getFromValue(String value) { MyEnum resp = null; MyEnum nodes[] = values(); for(int i = 0; i < nodes.length; i++) { if(nodes[i].value.equals(value)) { resp = nodes[i]; break; } } return resp; } 

Método O (1) inspirado en el código de ahorro generado que utiliza un hashmap.

 public enum USER { STUDENT("jon",0),TEACHER("tom",1); private static final Map map = new HashMap<>(); static { for (USER user : EnumSet.allOf(USER.class)) { map.put(user.getTypeName(), user.getIndex()); } } public static int findIndexByTypeName(String typeName) { return map.get(typeName); } private USER(String typeName,int index){ this.typeName = typeName; this.index = index; } private String typeName; private int index; public String getTypeName() { return typeName; } public void setTypeName(String typeName) { this.typeName = typeName; } public int getIndex() { return index; } public void setIndex(int index) { this.index = index; } } 

En Java 8, el patrón de Mapa estático es aún más fácil y es mi método preferido. Si desea utilizar Enum with Jackson, puede anular toString y usar eso en lugar de name, luego anotar con @JsonValue

 public enum MyEnum { BAR, BAZ; private static final Map MAP = Stream.of(MyEnum.values()).collect(Collectors.toMap(Enum::name, Function.identity())); public static MyEnum fromName(String name){ return MAP.get(name); } } public enum MyEnumForJson { BAR("bar"), BAZ("baz"); private static final Map MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity())); private final String value; MyEnumForJson(String value) { this.value = value; } @JsonValue @Override public String toString() { return value; } public static MyEnumForJson fromValue(String value){ return MAP.get(value); } } 

java.lang.Enum define varios métodos útiles, que están disponibles para todo el tipo de enumeración en Java:

  • Puede usar el método name() para obtener el nombre de cualquier constante Enum. String literal utilizado para escribir constantes enum es su nombre.
  • De forma similar values() método values() se puede usar para obtener una matriz de todas las constantes de Enum de un tipo Enum.
  • Y para la pregunta formulada, puede usar el método valueOf() para convertir cualquier cadena a la constante Enum en Java, como se muestra a continuación.
 public class EnumDemo06 { public static void main(String args[]) { Gender fromString = Gender.valueOf("MALE"); System.out.println("Gender.MALE.name() : " + fromString.name()); } private enum Gender { MALE, FEMALE; } } Output: Gender.MALE.name() : MALE 

En este fragmento de código, el método valueOf() devuelve una constante Enum Gender.MALE, nombre de llamada que devuelve "MALE" .

La biblioteca common-lang de Apache tiene una función estática org.apache.commons.lang3.EnumUtils.getEnum que asignará una cadena a su tipo Enum. La misma respuesta, en esencia, que Geoffreys, pero ¿por qué hacerla suya cuando ya está en libertad?

Agregando a la respuesta mejor clasificada, con una utilidad útil …

valueOf() arroja dos excepciones diferentes en los casos en que no le gusta su entrada.

  • IllegalArgumentException
  • NullPointerExeption

Si sus requisitos son tales que no tiene ninguna garantía de que su String definitivamente coincida con un valor enum, por ejemplo, si los datos de String provienen de una base de datos y podrían contener una versión anterior de la enumeración, entonces deberá manejar estos a menudo…

Así que aquí hay un método reutilizable que escribí que nos permite definir un Enum por defecto que se devolverá si el String que pasamos no coincide.

 private static > T valueOf( String name , T defaultVal) { try { return Enum.valueOf(defaultVal.getDeclaringClass() , name); } catch (IllegalArgumentException | NullPointerException e) { return defaultVal; } } 

Úselo así:

 public enum MYTHINGS { THINGONE, THINGTWO } public static void main(String [] asd) { valueOf("THINGTWO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGTWO valueOf("THINGZERO" , MYTHINGS.THINGONE);//returns MYTHINGS.THINGONE } 

Otra utilidad que se captura de forma inversa. Usando un valor que identifica ese Enum, no desde su nombre.

 import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.EnumSet; public class EnumUtil { /** * Returns the Enum of type enumType whose a * public method return value of this Enum is * equal to valor.
* Such method should be unique public, not final and static method * declared in Enum. * In case of more than one method in match those conditions * its first one will be chosen. * * @param enumType * @param value * @return */ public static > E from(Class enumType, Object value) { String methodName = getMethodIdentifier(enumType); return from(enumType, value, methodName); } /** * Returns the Enum of type enumType whose * public method methodName return is * equal to value.
* * @param enumType * @param value * @param methodName * @return */ public static
> E from(Class enumType, Object value, String methodName) { EnumSet enumSet = EnumSet.allOf(enumType); for (E en : enumSet) { try { String invoke = enumType.getMethod(methodName).invoke(en).toString(); if (invoke.equals(value.toString())) { return en; } } catch (Exception e) { return null; } } return null; } private static String getMethodIdentifier(Class enumType) { Method[] methods = enumType.getDeclaredMethods(); String name = null; for (Method method : methods) { int mod = method.getModifiers(); if (Modifier.isPublic(mod) && !Modifier.isStatic(mod) && !Modifier.isFinal(mod)) { name = method.getName(); break; } } return name; } }

Ejemplo:

 public enum Foo { ONE("eins"), TWO("zwei"), THREE("drei"); private String value; private Foo(String value) { this.value = value; } public String getValue() { return value; } } 

EnumUtil.from(Foo.class, "drei") devuelve Foo.THREE , porque usará getValue para que coincida con “drei”, que es un método público único, no final y no estático en Foo. En caso de que Foo tenga más que un método público, no final y no estático, por ejemplo, getTranslate que devuelve “drei”, se puede usar el otro método: EnumUtil.from(Foo.class, "drei", "getTranslate") .

¿Qué pasa?

 public enum MyEnum { FIRST, SECOND, THIRD; public static Optional fromString(String value){ try{ return Optional.of(MyEnum.valueOf(value)); }catch(Exception e){ return Optional.empty(); } } } 

Como todavía no se ha mencionado un switch versión, lo presento (reutilizando la enumeración de OP):

  private enum Blah { A, B, C, D; public static Blah byName(String name) { switch (name) { case "A": return A; case "B": return B; case "C": return C; case "D": return D; default: throw new IllegalArgumentException( "No enum constant " + Blah.class.getCanonicalName() + "." + name); } } } 

Como esto no da ningún valor adicional al método valueOf(String name) , solo tiene sentido definir un método adicional si queremos tener un comportamiento diferente. Si no queremos generar una IllegalArgumentException , podemos cambiar la implementación a:

  private enum Blah { A, B, C, D; public static Blah valueOfOrDefault(String name, Blah defaultValue) { switch (name) { case "A": return A; case "B": return B; case "C": return C; case "D": return D; default: if (defaultValue == null) { throw new NullPointerException(); } return defaultValue; } } } 

Al proporcionar un valor predeterminado, mantenemos el contrato de Enum.valueOf(String name) sin lanzar una IllegalArgumentException de manera que en ningún caso se devuelve null . Por lo tanto, arrojamos una NullPointerException si el nombre es null y en caso de default si defaultValue es null . Así es como funciona valueOfOrDefault .

Este enfoque adopta el diseño del Map Interfaz que proporciona un método Map.getOrDefault(Object key, V defaultValue) partir de Java 8.

Me gusta usar este tipo de proceso para analizar comandos como cadenas en enumeraciones. Normalmente tengo una de las enumeraciones como “desconocida”, por lo que ayuda a que la devuelvan cuando no se encuentran las demás (incluso sin distinción de mayúsculas y minúsculas) en lugar de nulas (lo que significa que no hay ningún valor). Por lo tanto, uso este enfoque.

 static > Enum getEnumValue(String what, Class enumClass) { Enum unknown=null; for (Enum enumVal: enumClass.getEnumConstants()) { if (what.compareToIgnoreCase(enumVal.name()) == 0) { return enumVal; } if (enumVal.name().compareToIgnoreCase("unknown") == 0) { unknown=enumVal; } } return unknown; }