首页 文章

如何从Java中的字符串值获取枚举值?

提问于
浏览
1690

说我有一个只是的枚举

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

我想找到一个字符串的枚举值,例如 "A" ,它将是 Blah.A . 怎么可能这样做?

Enum.valueOf() 是我需要的方法吗?如果是这样,我将如何使用它?

24 回答

  • 68

    另一个实用程序以相反方式捕获使用标识Enum的值,而不是其名称 .

    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>.
    * 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>.
    * * @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; } }

    例:

    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") 返回 Foo.THREE ,因为它将使用 getValue 来匹配"drei",这是唯一的公共,而不是Foo中的final和非静态方法 . 如果Foo具有多个on public,而不是final和not static方法,例如, getTranslate 返回"drei",则可以使用另一种方法: EnumUtil.from(Foo.class, "drei", "getTranslate") .

  • 46

    另一种方法是使用Enum的隐式静态方法 name() . name将返回用于创建该枚举的确切字符串,该字符串可用于检查提供的字符串:

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

    测试:

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

    //it will print B  B
    

    灵感:10 Examples of Enum in Java

  • 1

    添加到最受好评的答案,有用的实用程序......

    valueOf() 在不喜欢其输入的情况下抛出两个不同的异常 .

    • IllegalArgumentException

    • NullPointerExeption

    如果您的要求不能保证您的String肯定会与枚举值匹配,例如,如果String数据来自数据库并且可能包含旧版本的枚举,那么您将需要处理这些经常...

    所以这里是我编写的一个可重用的方法,它允许我们定义一个默认的Enum,如果我们传递的String不匹配则返回 .

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

    像这样用它:

    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
    }
    
  • 740

    您可能需要这样:

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

    还有一个补充:

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

    这将通过字符串化的枚举名称返回值,例如如果您在fromEnumName中提供“PERSON”,它将返回Enum的值,即“Person”

  • 24

    我的2美分:使用Java8 Streams检查确切的字符串:

    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 valueOf(String s) throws IllegalArgumentException {
            return Arrays.stream(MyEnum.values())
                    .filter(v -> v.value.equals(s))
                    .findFirst()
                    .orElseThrow(() -> new IllegalArgumentException("unknown value: " + s));
        }
    }
    

    编辑

    将函数重命名为 valueOf() (或 fromString() ),因为使用该约定命名它,您将从Java语言本身获得一些好处;例如:

  • 1952
    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;
    }
    
  • 16

    java.lang.Enum 定义了几种有用的方法,可用于Java中的所有枚举类型:

    • 您可以使用 name() 方法获取任何枚举常量的名称 . 用于编写枚举常量的字符串文字是它们的名称 .

    • 类似地, values() 方法可用于从Enum类型获取所有Enum常量的数组 .

    • 对于提出的问题,您可以使用 valueOf() 方法将任何String转换为Java中的Enum常量,如下所示 .

    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
    

    在此代码段中, valueOf() 方法返回一个Enum常量Gender.MALE,在其上调用name返回 "MALE" .

  • 5

    是的, Blah.valueOf("A") 会给你 Blah.A .

    请注意,名称必须完全匹配,包括大小写: Blah.valueOf("a")Blah.valueOf("A ") 都抛出 IllegalArgumentException .

    静态方法 valueOf()values() 是在编译时创建的,不会出现在源代码中 . 但它们确实出现在Javadoc中;例如,Dialog.ModalityType显示了这两种方法 .

  • 7

    要添加到先前的答案,并解决一些关于null和NPE的讨论,我正在使用Guava Optionals来处理缺席/无效案例 . 这适用于URI /参数解析 .

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

    对于那些不知道的人,这里有一些关于使用Optional避免null的更多信息:https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

  • 13

    如果你没有't want to write your own utility use Google'的guava库:

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

    与内置的java函数不同,它让你检查Blah中是否存在A并且不会抛出异常 .

  • 1

    你也应该小心你的情况 . 让我解释一下:做 Blah.valueOf("A") 工作,但是 Blah.valueOf("a") 将不起作用 . 然后 Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) 再次起作用 .

    edit
    基于tc. commentjava docstoUpperCase 更改为 toUpperCase(Locale.ENGLISH)

    edit2 在Android上你应该使用Locale.US,作为sulai points out .

  • 34

    使用 Blah.valueOf(string) 是最好的,但您也可以使用 Enum.valueOf(Blah.class, string) .

  • 6

    在Java 8中,静态Map模式更容易,是我的优先方法 . 如果你想使用Enum with Jackson,你可以覆盖toString并使用它代替名称,然后用 @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);
        }
    }
    
  • 5

    Apache的commons-lang库有一个静态函数org.apache.commons.lang3.EnumUtils.getEnum,它将String映射到你的Enum类型 . 基本上和Geoffreys一样的答案,但为什么在野外已经存在的时候自己滚动 .

  • 3

    我喜欢使用这种过程将命令作为字符串解析为枚举 . 我通常将其中一个枚举称为“未知”,因此当找不到其他枚举时(即使基于不区分大小写)而不是null(这意味着没有值),它会有所帮助 . 因此我使用这种方法 .

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

    使用Guava库的解决方案 . 方法getPlanet()不区分大小写,因此getPlanet(“MerCUrY”)将返回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();
       }
    }
    
  • 1

    使用来自Joshua Bloch,Effective Java的模式:

    (为简洁起见,简化)

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

    另见:

    Oracle Java Example using Enum and Map of instances

    Execution order of of static blocks in an Enum type

    How can I lookup a Java enum from its String value

  • 2

    O(1)方法受益于使用散列映射的thrift生成的代码 .

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

    这是一个可以为任何枚举执行此操作的方法,并且不区分大小写 .

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

    由于尚未提及 switch -version,我将其介绍(重用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);
          }
        }
      }
    

    由于这不会给 valueOf(String name) 方法带来任何附加值,因此如果我们想要有不同的行为,那么定义一个额外的方法才有意义 . 如果我们不想提出 IllegalArgumentException ,我们可以将实现更改为:

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

    通过提供默认值,我们保持contractcontract而不会以这种方式抛出 IllegalArgumentException ,在任何情况下都不会返回 null . 因此,如果名称为 null ,则抛出 NullPointerException ,如果 defaultValuenull ,则抛出 default . 这就是 valueOfOrDefault 的工作方式 .

    这种方法采用了 Map -Interface的设计,它提供了Java 8中的方法 Map.getOrDefault(Object key, V defaultValue) .

  • 105

    在Java 8或更高版本中,使用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);
        }
    }
    
  • 28

    如果文本与枚举值不同,则为另一种解决方案:

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

    这是我使用的一个漂亮的实用程序:

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

    然后在我的枚举类中,我通常会这样做以节省一些输入:

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

    如果您的枚举不是全部大写,只需更改 Enum.valueOf 行即可 .

    太糟糕了,因为 T 被删除,所以不能使用 T.class Enum.valueOf .

  • 10

    关于什么?

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

相关问题