values - java enum with value




Recherche Java enum par valeur de chaîne (16)

Dire que j'ai une énumération 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 Enum.valueOf() la méthode dont j'ai besoin? Si oui, comment pourrais-je l'utiliser?


Ajoutant à la réponse la mieux notée, avec un utilitaire utile ...

valueOf() renvoie deux exceptions différentes dans les cas où il n'aime pas son entrée.

  • IllegalArgumentException
  • NullPointerExeption

Si vos besoins sont tels que vous n'avez aucune garantie que votre chaîne correspondra définitivement à une valeur enum, par exemple si les données de chaîne proviennent d'une base de données et pourraient contenir une ancienne version de l'énumération, vous devrez les gérer souvent...

Donc, voici une méthode réutilisable que j'ai écrite qui nous permet de définir un Enum par défaut à renvoyer 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
}

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

J'aime utiliser ce genre de processus pour analyser les commandes comme des chaînes dans les énumérations. J'ai normalement l'une des énumérations comme "inconnue" donc il est utile d'avoir cela retourné quand les autres ne sont pas trouvés (même sur une base insensible à la casse) plutôt que null (ce qui signifie qu'il n'y a pas de valeur). Par conséquent, j'utilise 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;
}


Mes 2 cents ici: en utilisant Java8 Streams + en vérifiant 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));
    }
}

** MODIFIER **

Renommé la fonction à fromString() depuis l'avoir nommé en utilisant cette convention, vous obtiendrez quelques avantages du langage Java lui-même; par exemple:

  1. Conversion directe des types à l'annotation HeaderParam

Oui, Blah.valueOf("A") vous donnera Blah.A

Notez que le nom doit correspondre exactement à la casse: Blah.valueOf("a") et Blah.valueOf("A ") lancent une 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 affiche les deux méthodes.


Qu'en est-il de?

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

Si vous ne voulez pas écrire votre propre utilitaire, utilisez la bibliothèque guava de Google:

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

Contrairement à la fonction java intégrée, elle vérifie si A est présent dans Blah et ne lance pas d'exception.


Un autre utilitaire capturant en sens inverse. En utilisant une valeur qui identifie Enum, pas 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") renvoie Foo.THREE , car il utilisera getValue pour faire correspondre "drei", qui est une méthode publique unique, non finale et non statique dans Foo. Dans le cas où Foo a plus que sur une méthode publique, non finale et non statique, par exemple, getTranslate qui retourne "drei", l'autre méthode peut être utilisée: EnumUtil.from(Foo.class, "drei", "getTranslate") .


Une autre façon de le faire en utilisant la méthode statique implicite name() de Enum. name retournera la chaîne exacte utilisée pour créer cette énumération qui peut être utilisée 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");
    }
}

Essai:

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

//it will print B  B

inspiration: 10 exemples d'énumération en Java


Utiliser Blah.valueOf(string) est préférable mais vous pouvez aussi utiliser Enum.valueOf(Blah.class, string) .


Utilisez le motif de Joshua Bloch, Java efficace :

(simplifié pour la brièveté)

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

Regarde aussi:

Oracle Java Exemple utilisant Enum et Map des instances

Ordre d'exécution des blocs statiques dans un type Enum

Comment puis-je rechercher une énumération Java à partir de sa valeur String


Voici une méthode qui peut le faire pour tout Enum, 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()
    ));
}

Vous devriez également être prudent avec votre cas. Laissez-moi vous expliquer: faire Blah.valueOf("A") fonctionne, mais Blah.valueOf("a") ne fonctionnera pas. Puis à nouveau Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) fonctionnerait.

modifier
Changé toUpperCase to toUpperCase(Locale.ENGLISH) basé sur tc. commenter et les docs java

edit2 Sur Android, vous devriez utiliser Locale.US , comme le souligne sulai .


java.lang.Enum définit plusieurs méthodes utiles, disponibles pour tous les types d'énumération dans Java:

  • Vous pouvez utiliser la méthode name() pour obtenir le nom de toutes les constantes Enum. Le littéral de chaîne utilisé pour écrire des constantes enum est leur nom.
  • De même values() méthode values() peut être utilisée pour obtenir un tableau de toutes les constantes Enum d'un type Enum.
  • Et pour la question posée, vous pouvez utiliser la méthode valueOf() pour convertir n'importe quelle chaîne en Enum constante 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 cet extrait de code, la méthode valueOf() renvoie une constante Enum Gender.MALE, en appelant le nom sur lequel renvoie "MALE" .


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




enums