Domanda

Dire che ho un enum che è solo

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

e vorrei trovare il valore enum di una stringa, ad esempio " A " che sarebbe Blah.A . Come sarebbe possibile farlo?

Enum.valueOf () è il metodo di cui ho bisogno? In tal caso, come dovrei usarlo?

È stato utile?

Soluzione

Sì, Blah.valueOf (" A ") ti darà Blah.A .

Nota che il nome deve essere una corrispondenza esatta , incluso case: Blah.valueOf (" a ") e Blah.valueOf (" A ") entrambi generano un IllegalArgumentException .

I metodi statici valueOf () e valori () vengono creati in fase di compilazione e non vengono visualizzati nel codice sorgente. Appaiono comunque in Javadoc; ad esempio, Dialog.ModalityType mostra entrambi i metodi.

Altri suggerimenti

Un'altra soluzione se il testo non è uguale al valore di enumerazione:

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

Ecco una bella utility che uso:

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

Quindi nella mia classe enum di solito ho questo per salvare un po 'di battitura:

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

Se le tue enumerazioni non sono tutte maiuscole, basta cambiare la riga Enum.valueOf .

Peccato che non posso usare T.class per Enum.valueOf poiché T viene cancellato.

Dovresti anche stare attento con il tuo caso. Mi spiego: fare Blah.valueOf (" A ") funziona, ma Blah.valueOf (" a ") non funzionerà. Quindi di nuovo Blah.valueOf (" a " .toUpperCase (Locale.ENGLISH)) funzionerebbe.

modifica
Modificato da toUpperCase a toUpperCase (Locale.ENGLISH) in base a tc. commento e il documenti java

edit2 Su Android dovresti usare Locale.US , come sulai sottolinea .

Usa lo schema di Joshua Bloch, Efficace Java :

(semplificato per brevità)

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

Vedi anche:

Esempio di Oracle Java che utilizza Enum e Map of casi

Ordine di esecuzione di di blocchi statici in un tipo Enum

Come posso cercare un enum Java dal suo valore String

Ecco un metodo che può farlo per qualsiasi Enum, senza distinzione tra maiuscole e minuscole.

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

L'uso di Blah.valueOf (stringa) è il migliore, ma puoi usare anche Enum.valueOf (Blah.class, string) .

Se non vuoi scrivere la tua utility, usa libreria:

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

A differenza della funzione java integrata, ti consente di verificare se A è presente in Blah e non genera un'eccezione.

I miei 2 centesimi qui: utilizzo Java8 Streams + controllo di una stringa esatta:

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 **

Rinominata la funzione in fromString () dal momento che la nomina usando quella convenzione, otterrai alcuni vantaggi dal linguaggio Java stesso; ad esempio:

  1. Conversione diretta dei tipi nell'annotazione HeaderParam

In Java 8 o versioni successive, utilizzando Stream :

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 Optional<Blah> fromText(String text) {
        return Arrays.stream(values())
          .filter(bl -> bl.text.equalsIgnoreCase(text))
          .findFirst();
    }
}

Potrebbe essere necessario:

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'altra aggiunta:

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

Questo ti restituirà il valore in base a un nome enumerato per es. se fornisci " PERSONA " nel fromEnumName ti restituirà il valore di Enum, ad es. " Person "

Un altro modo per farlo utilizzando il metodo statico implicito name () di Enum. name restituirà la stringa esatta utilizzata per creare quell'enum che può essere utilizzato per verificare la stringa fornita:

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

ispirazione: 10 esempi di Enum in Java

Soluzione che utilizza librerie Guava. Il metodo getPlanet () non fa distinzione tra maiuscole e minuscole, quindi getPlanet (" MerCUrY ") restituirà 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 <Planet> possible = Enums.getIfPresent(Planet.class, val);
      if (!possible.isPresent()) {
         throw new IllegalArgumentException(val + "? There is no such planet!");
      }
      return possible.get();
   }
}

Per aggiungere alle risposte precedenti e affrontare alcune delle discussioni su null e NPE sto usando Guava Optionals per gestire casi assenti / non validi. Funziona benissimo per l'analisi URI / parametri.

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

Per coloro che non sono a conoscenza, ecco alcune ulteriori informazioni su come evitare null con Facoltativo: https: // code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

In Java 8 il modello di mappa statica è ancora più semplice ed è il mio metodo preferito. Se si desidera utilizzare l'Enum con Jackson, è possibile sovrascrivere String e utilizzarlo al posto del nome, quindi annotare con @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);
    }
}
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;
}

Metodo O (1) ispirato al codice generato dalla parsimonia che utilizza una hashmap.

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

}

java.lang.Enum definisce diversi metodi utili, disponibili per tutti i tipi di enumerazione in Java:

  • È possibile utilizzare il metodo name () per ottenere il nome di qualsiasi costante Enum. Il letterale stringa usato per scrivere costanti di enum è il loro nome.
  • Allo stesso modo il metodo valori () può essere usato per ottenere una matrice di tutte le costanti Enum da un tipo Enum.
  • E per la domanda posta, puoi usare il metodo valueOf () per convertire qualsiasi costante String in Enum in Java, come mostrato sotto.
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

In questo frammento di codice, il metodo valueOf () restituisce una costante Enum Gender.MALE, chiamando il nome che restituisce " MALE " .

La libreria commons-lang di Apache ha una funzione statica org.apache.commons.lang3.EnumUtils.getEnum che mapperà una stringa sul tuo tipo Enum. Stessa risposta essenzialmente come Geoffreys, ma perché farlo da solo quando è già in circolazione.

Aggiungendo alla risposta più votata, con un'utilità utile ...

valueOf () genera due diverse eccezioni nei casi in cui non gli piace il suo input.

  • IllegalArgumentException
  • NullPointerExeption

Se i tuoi requisiti sono tali da non avere alcuna garanzia che la tua String corrisponderà sicuramente a un valore enum, ad esempio se i dati String provengono da un database e potrebbero contenere una versione precedente dell'enum, allora avrai bisogno per gestirli spesso ...

Quindi ecco un metodo riutilizzabile che ho scritto che ci consente di definire un Enum predefinito da restituire se la stringa che passiamo non corrisponde.

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

Usalo in questo modo:

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
}

Che dire?

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

Un'altra utilità catturata in modo inverso. Utilizzando un valore che identifica quell'Enum, non dal suo nome.

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

Esempio:

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 ") restituisce Foo.THREE , perché utilizzerà getValue per abbinare " ; drei " ;, che è un metodo pubblico unico, non definitivo e non statico in Foo. Nel caso in cui Foo abbia un metodo più che pubblico, non definitivo e non statico, ad esempio getTranslate che restituisce "drei", è possibile utilizzare l'altro metodo: EnumUtil.from (Foo. class ", drei", "getTranslate") .

Dato che l'opzione non è stata ancora menzionata, la presento (riutilizzando l'enumerazione di 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);
      }
    }
  }

Dato che questo non dà alcun valore aggiuntivo al metodo valueOf (String name) , ha senso definire un metodo aggiuntivo solo se vogliamo avere un comportamento diverso. Se non vogliamo aumentare un IllegalArgumentException possiamo cambiare l'implementazione in:

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

Fornendo un valore predefinito manteniamo contratto di Enum.valueOf (String name) senza lanciare un IllegalArgumentException in quel modo che in non viene restituito null . Pertanto lanciamo un NullPointerException se il nome è null e in caso di default se defaultValue è null . Ecco come funziona valueOfOrDefault .

Questo approccio adotta il design del Map -Interface che fornisce un metodo Map.getOrDefault (Chiave oggetto, V defaultValue) a partire da Java 8.

Mi piace usare questo tipo di processo per analizzare i comandi come stringhe in enumerazioni. Normalmente ho una delle enumerazioni come "sconosciuta" quindi aiuta a restituire ciò quando gli altri non vengono trovati (anche su base insensibile al maiuscolo / minuscolo) piuttosto che nulli (il che significa che non ha valore). Quindi uso questo approccio.

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

Il modo più veloce per ottenere il nome di enum è creare una mappa del testo e del valore di enum all'avvio dell'applicazione e per ottenere il nome chiamare la funzione Blah.getEnumName ():

public enum Blah {
    A("text1"),
    B("text2"),
    C("text3"),
    D("text4");

    private String text;
    private HashMap<String, String> map;
    Blah(String text) {
    this.text = text;
    }

    public String getText() {
      return this.text;
    }

    static{
      createMapOfTextAndName();
    }

    public static void createMapOfTextAndName() {
        map = new HashMap<String, String>();
        for (Blah b : Blah.values()) {
             map.put(b.getText(),b.toString());
        }
    }
    public static String getEnumName(String text) {
        return map.get(text.toLowerCase());
    } 
}

Enum è molto utile, ho usato molto Enum per aggiungere una descrizione per alcuni campi in diverse lingue, come nell'esempio seguente:

public enum Status {

    ACT(new String[] { "Accepted", "مقبول" }),
    REJ(new String[] { "Rejected", "مرفوض" }),
    PND(new String[] { "Pending", "في الانتظار" }),
    ERR(new String[] { "Error", "خطأ" }),
    SNT(new String[] { "Sent", "أرسلت" });

    private String[] status;

    public String getDescription(String lang) {
        return lang.equals("en") ? status[0] : status[1];
    }

    Status(String[] status) {
        this.status = status;
    }
}

Quindi puoi recuperare la descrizione in modo dinamico in base al codice della lingua passato al metodo getDescription (String lang) , ad esempio:

String statusDescription = Status.valueOf("ACT").getDescription("en");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top