Comment obtenir une valeur enum à partir d'une valeur string en Java?
Dire que j'ai un enum qui est juste
public enum Blah {
A, B, C, D
}
et je voudrais trouver la valeur enum d'une chaîne, par exemple "A"
qui serait Blah.A
. Comment serait-il possible de faire cela?
est-ce que le Enum.valueOf()
est la méthode dont j'ai besoin? Dans l'affirmative, comment puis-je m'en servir?
24 réponses
Oui, Blah.valueOf("A")
vous donnera Blah.A
.
notez que le nom doit être un exact match, y compris le cas: Blah.valueOf("a")
et Blah.valueOf("A ")
les deux jeter un IllegalArgumentException
.
les méthodes statiques valueOf()
et values()
sont créées au moment de la compilation et n'apparaissent pas dans le code source. Ils apparaissent dans Javadoc, cependant; par exemple, Dialog.ModalityType
montre les deux méthodes.
une autre solution si le texte n'est pas le même que la valeur d'énumération:
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;
}
}
voici un utilitaire astucieux que j'utilise:
/**
* A common method for all enums since they can't have another base class
* @param <T> Enum type
* @param c enum type. All enums must be all caps.
* @param string case insensitive
* @return corresponding enum, or null
*/
public static <T extends Enum<T>> T getEnumFromString(Class<T> c, String string) {
if( c != null && string != null ) {
try {
return Enum.valueOf(c, string.trim().toUpperCase());
} catch(IllegalArgumentException ex) {
}
}
return null;
}
alors dans ma classe d'enum j'ai habituellement ceci pour sauver quelques dactylographier:
public static MyEnum fromString(String name) {
return getEnumFromString(MyEnum.class, name);
}
si vos enums ne sont pas tous des capuchons, changez simplement la ligne Enum.valueOf
.
dommage que je ne puisse pas utiliser T.class
pour Enum.valueOf
comme T
est effacé.
vous devriez également être prudent avec votre cas. Laissez-moi vous expliquer: faire Blah.valueOf("A")
fonctionne, mais Blah.valueOf("a")
ne fonctionnera pas. Blah.valueOf("a".toUpperCase(Locale.ENGLISH))
fonctionnerait.
modifier
Modifié toUpperCase
en toUpperCase(Locale.ENGLISH)
basé sur tc. commentaire et le java docs
edit2
Sur android, vous devez utiliser Locale.US
, sulai points .
utiliser le modèle de Joshua Bloch, Java efficace :
(simplifié par concision)
enum MyEnum {
ENUM_1("A"),
ENUM_2("B");
private String name;
private static final Map<String,MyEnum> 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<String,MyEnum> map = new ConcurrentHashMap<String,MyEnum>();
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);
}
}
Voir aussi:
Oracle Exemple Java à l'aide de l'Enum et Carte des instances
ordre d'exécution de blocs statiques de type Enum
Comment puis-je chercher un Java enum à partir de sa chaîne valeur
Voici une méthode qui peut le faire pour n'importe quel Énum, et est insensible à la casse.
/**
* Finds the value of the given enumeration by name, case-insensitive.
* Throws an IllegalArgumentException if no match is found.
**/
public static <T extends Enum<T>> T valueOfIgnoreCase(
Class<T> 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()
));
}
utiliser Blah.valueOf(string)
est préférable, mais vous pouvez utiliser Enum.valueOf(Blah.class, string)
ainsi.
si vous ne voulez pas écrire votre propre utilitaire utilisez guava "de Google 151930920" bibliothèque:
Enums.getIfPresent(Blah.class, "A")
contrairement à la fonction java intégrée, il faut vérifier si A est présent dans Blah et ne jette pas d'exception.
vous pourriez avoir besoin de ceci:
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;
}
}
Un Ajout De Plus:
public static String fromEnumName(String parameterName) {
if (parameterName != null) {
for (DQJ objType : DQJ.values()) {
if (parameterName.equalsIgnoreCase(objType.name())) {
return objType.parameterName;
}
}
}
return null;
}
cela vous retournera la valeur par un nom Enum Stringifié pour par exemple si vous fournissez "personne" dans le nom de fromenum il vous rendra la valeur D'Enum i.e." personne "
en Java 8 ou plus tard, en utilisant 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);
}
}
mes 2 cents ici: en utilisant Java8 Streams + vérification d'une chaîne exacte:
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 * *
renommé la fonction en fromString()
depuis l'avoir nommée en utilisant cette convention, vous obtiendrez certains avantages du langage Java lui-même; par exemple:
une autre façon de le faire en utilisant la méthode statique implicite name()
de L'Enum. nom retournera la chaîne exacte utilisée pour créer cet enum qui peut être utilisé pour vérifier la chaîne fournie:
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");
}
}
Test:
System.out.println(Blah.getEnum("B").name());
//it will print B B
inspiration: 10 Exemples D'Enum en Java
Solution utilisant des bibliothèques de goyaves. La méthode getPlanet () est insensible à la casse, donc getPlanet ("Mercure") retournera planète.MERCURE.
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 <Planet> possible = Enums.getIfPresent(Planet.class, val);
if (!possible.isPresent()) {
throw new IllegalArgumentException(val + "? There is no such planet!");
}
return possible.get();
}
}
pour ajouter aux réponses précédentes, et répondre à certaines des discussions autour nulls et NPE j'utilise des options de goyave pour traiter les cas absents/invalides. Cela fonctionne très bien pour URI/parameter parsing.
public enum E {
A,B,C;
public static Optional<E> fromString(String s) {
try {
return Optional.of(E.valueOf(s.toUpperCase()));
} catch (IllegalArgumentException|NullPointerException e) {
return Optional.absent();
}
}
}
pour ceux qui ne le savent pas, voici plus d'informations sur la façon d'éviter null avec option: 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;
}
O(1) méthode inspirée de l'épargne code généré qui utilisent une table de hachage.
public enum USER {
STUDENT("jon",0),TEACHER("tom",1);
private static final Map<String, Integer> 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 le modèle de carte statique est encore plus facile et est ma méthode préferée. Si vous voulez utiliser L'Enum avec Jackson vous pouvez outrepasser toString et utiliser cela à la place du nom, puis annoter avec @JsonValue
public enum MyEnum {
BAR,
BAZ;
private static final Map<String, MyEnum> 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<String, MyEnumForJson> 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
définit plusieurs méthodes utiles, qui est disponible pour tous les types d'énumération en Java:
- vous pouvez utiliser la méthode
name()
pour obtenir le nom de n'importe quelles constantes Enum. String literal utilisé pour écrire les constantes d'enum est leur nom. - de la même manière
values()
méthode peut être utilisée pour obtenir un tableau de toutes les constantes Enum à partir d'un type Enum. - et pour la question posée, vous pouvez utiliser la méthode
valueOf()
pour convertir n'importe quelle chaîne de caractères en constante Enum en Java, comme indiqué ci-dessous.
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
dans ce code snippet, valueOf()
méthode retourne un genre constant Enum.Homme, appelant nom sur qui renvoie "MALE"
.
Apache commons-lang bibliothèque a une fonction statique org.Apache.commun.lang3.EnumUtils.getEnum qui mappera une chaîne de caractères à votre type Enum. Même réponse essentiellement que Geoffreys, mais pourquoi rouler le vôtre quand il est là-bas dans la nature déjà.
ajoute à la réponse la mieux cotée, avec un utilitaire utile...
valueOf()
Lance deux Exceptions différentes dans les cas où il n'aime pas son entrée.
-
IllegalArgumentException
-
NullPointerExeption
si vos exigences sont telles que vous n'avez aucune garantie que votre chaîne de caractères correspondra définitivement à une valeur enum, par exemple si les données de la chaîne proviennent d'une base de données et pourrait contenir une ancienne version de l'enum, alors vous aurez besoin de gérer ces souvent...
voici donc une méthode réutilisable que j'ai écrite qui nous permet de définir un Enum par défaut à retourner si la chaîne que nous passons ne correspond pas.
private static <T extends Enum<T>> T valueOf( String name , T defaultVal) {
try {
return Enum.valueOf(defaultVal.getDeclaringClass() , name);
} catch (IllegalArgumentException | NullPointerException e) {
return defaultVal;
}
}
utilisez - le comme ceci:
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
}
un autre utilitaire capturant en sens inverse. En utilisant une valeur qui identifie cet Enum, pas à partir de son nom.
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.EnumSet;
public class EnumUtil {
/**
* Returns the <code>Enum</code> of type <code>enumType</code> whose a
* public method return value of this Enum is
* equal to <code>valor</code>.<br/>
* 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 extends Enum<E>> E from(Class<E> enumType, Object value) {
String methodName = getMethodIdentifier(enumType);
return from(enumType, value, methodName);
}
/**
* Returns the <code>Enum</code> of type <code>enumType</code> whose
* public method <code>methodName</code> return is
* equal to <code>value</code>.<br/>
*
* @param enumType
* @param value
* @param methodName
* @return
*/
public static <E extends Enum<E>> E from(Class<E> enumType, Object value, String methodName) {
EnumSet<E> 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;
}
}
exemple:
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")
returns Foo.THREE
, parce qu'il va utiliser getValue
pour correspondre à "drei", qui est public unique, Pas finale et pas méthode statique dans Foo.
Dans le cas de Foo a plus que sur la méthode publique, Pas finale et non statique, par exemple, getTranslate
qui renvoie" drei", l'autre méthode peut être utilisé: EnumUtil.from(Foo.class, "drei", "getTranslate")
.
à quel sujet?
public enum MyEnum {
FIRST,
SECOND,
THIRD;
public static Optional<MyEnum> fromString(String value){
try{
return Optional.of(MyEnum.valueOf(value));
}catch(Exception e){
return Optional.empty();
}
}
}
comme une switch
- la version n'a pas été mentionnée mais je l'introduis (réutilisant OP's enum):
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);
}
}
}
puisque cela ne donne aucune valeur supplémentaire à la méthode valueOf(String name)
, cela n'a de sens que de définir une méthode supplémentaire si nous voulons avoir un comportement différent. Si nous ne voulons pas soulever un IllegalArgumentException
nous pouvons changer la mise en œuvre à:
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;
}
}
}
en fournissant une valeur par défaut, nous conservons le contrat de Enum.valueOf(String name)
sans lancer un IllegalArgumentException
de telle manière qu'en aucun cas null
ne soit retourné. Par conséquent, nous lançons un NullPointerException
si le nom est null
et dans le cas de default
si defaultValue
est null
. C'est comme ça que valueOfOrDefault
fonctionne.
cette approche adopte la conception de Map
- Interface qui fournit une méthode Map.getOrDefault(Object key, V defaultValue)
à partir de Java 8.
j'aime utiliser ce genre de processus pour analyser les commandes comme des chaînes dans des énumérations. J'ai normalement une des énumérations comme "inconnue" de sorte qu'il est utile d'avoir ce retour lorsque les autres ne sont pas trouvés (même sur une base insensible de cas) plutôt que nul (ce qui signifie qu'il n'y a aucune valeur). J'ai donc utiliser cette approche.
static <E extends Enum<E>> Enum getEnumValue(String what, Class<E> enumClass) {
Enum<E> unknown=null;
for (Enum<E> enumVal: enumClass.getEnumConstants()) {
if (what.compareToIgnoreCase(enumVal.name()) == 0) {
return enumVal;
}
if (enumVal.name().compareToIgnoreCase("unknown") == 0) {
unknown=enumVal;
}
}
return unknown;
}