代码之家  ›  专栏  ›  技术社区  ›  Royce

从字符串[重复]获取枚举值

  •  -3
  • Royce  · 技术社区  · 5 年前

    假设我有一个枚举

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

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

    Enum.valueOf() 我需要的方法?如果是的话,我怎么用这个?

    0 回复  |  直到 6 年前
        1
  •  2113
  •   Michael Myers KitsuneYMG    7 年前

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

    请注意,名称必须是 准确的 匹配,包括大小写: Blah.valueOf("a") Blah.valueOf("A ") 两人都投了一个 IllegalArgumentException .

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

        2
  •  808
  •   deHaar    6 年前

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

    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;
        }
    }
    
        3
  •  115
  •   vaxquis user2577497    10 年前

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

    /**
     * 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.class 对于 枚举值 作为 T 被删除。

        4
  •  75
  •   deHaar    6 年前

    使用Joshua Bloch的图案, 通用程序设计 :

    (为了简洁而简化)

    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

        5
  •  73
  •   Community user43968    7 年前

    你也应该小心处理你的案子。让我解释一下:做 Blah.valueOf("A") 有效,但是 Blah.valueOf("a") 不起作用。然后再来一次 Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) 会有用的。

    编辑
    改变 toUpperCase toUpperCase(Locale.ENGLISH) 基于 tc. comment 以及 java docs

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

        6
  •  37
  •   Radiodef    9 年前

    这里有一个方法可以对任何枚举执行此操作,并且不区分大小写。

    /** 
     * 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()
        ));
    }
    
        7
  •  32
  •   raffian Eric Reid    11 年前

    使用 Blah.valueOf(string) 最好不过你可以用 Enum.valueOf(Blah.class, string) 也。

        8
  •  26
  •   Andrejs    10 年前

    如果你不想写你自己的工具,使用谷歌的 图书馆:

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

    与内置的Java函数不同,它让我们检查是否存在BLAH,并且不会抛出异常。

        9
  •  23
  •   Manu Artero Rajeev Dutta    6 年前

    这里我的2分:使用Java8流+检查精确的字符串:

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

    **编辑**

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

    1. Direct conversion of types at HeaderParam annotation
        10
  •  23
  •   Hans Schreuder    5 年前

    在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 Optional<Blah> fromText(String text) {
            return Arrays.stream(values())
              .filter(bl -> bl.text.equalsIgnoreCase(text))
              .findFirst();
        }
    }
    
        11
  •  14
  •   Murtaza Kanchwala    9 年前

    您可能需要这样做:

    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”,它将返回枚举的值,即“person”。

        12
  •  11
  •   Sameera Thilakasiri    13 年前

    使用隐式静态方法的另一种方法 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

        13
  •  7
  •   javabrew    10 年前

    使用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();
       }
    }
    
        14
  •  6
  •   Radiodef    9 年前

    为了增加前面的答案,并解决一些关于nulls和npe的讨论,我使用guava选项来处理缺席/无效的案例。这对于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();
            }
        }
    }
    

    对于那些不知道的人,下面是关于使用可选选项避免空值的更多信息: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional

        15
  •  6
  •   Novaterata    7 年前

    在Java 8中,静态映射模式更容易,是我的预处理方法。如果要将枚举与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);
        }
    }
    
        16
  •  5
  •   Radiodef    9 年前
    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;
    }
    
        17
  •  4
  •   Sisyphus    9 年前

    o(1)方法的灵感来源于节俭的代码,该代码使用哈希图。

    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;
            }
    
    }
    
        18
  •  3
  •   Radiodef    9 年前

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

    • 你可以用 name() 方法获取任何枚举常量的名称。用于写入枚举常量的字符串文字是它们的名称。
    • 类似地 values() 方法可用于从枚举类型获取所有枚举常量的数组。
    • 对于所问的问题,您可以使用 valueOf() 方法,将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
    

    在这个代码段中, 的值() 方法返回一个枚举常量gender.male,并对其调用名称 "MALE" .

        19
  •  3
  •   pjklauser    9 年前

    阿帕奇的 commons-lang 库具有静态函数 org.apache.commons.lang3.EnumUtils.getEnum 它将字符串映射到枚举类型。基本上和杰弗里斯的答案一样,但为什么当它已经在野外的时候,还要自己滚呢?

        20
  •  3
  •   user812786 bojeil    7 年前

    添加到最热门的答案,有一个有用的实用程序…

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

    • IllegalArgumentException
    • NullPointerExeption

    如果您的要求是这样的,您没有任何保证您的字符串一定会匹配枚举值,例如,如果字符串数据来自数据库并且可能包含枚举的旧版本,那么您需要经常处理这些…

    所以这里有一个我编写的可重用方法,它允许我们定义一个默认的枚举,如果我们传递的字符串不匹配,它将被返回。

    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
    }
    
        21
  •  2
  •   DCO    7 年前

    怎么办?

    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();
            }
        }
    }
    
        22
  •  1
  •   Moesio    8 年前

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

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

    例子:

    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中唯一的公共方法,不是最终方法,也不是静态方法。 例如,如果foo有超过on public、非final和非static方法, getTranslate 它返回“drei”,另一种方法可以使用: EnumUtil.from(Foo.class, "drei", "getTranslate") .

        23
  •  1
  •   LuCio    6 年前

    作为一个 switch -还没有提到版本,我将介绍它(重用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;
          }
        }
      }
    

    通过提供默认值,我们保留 contract 属于 Enum.valueOf(String name) 不扔一个 非法数据异常 在任何情况下 null 返回。因此我们抛出一个 NullPointerException 如果名字是 无效的 如果 default 如果 defaultValue 无效的 . 就是这样 valueOfOrDefault 作品。

    这种方法采用了 Map -提供方法的接口 Map.getOrDefault(Object key, V defaultValue) 如Java 8所示。

        24
  •  1
  •   Ebraheem Alrabeea    5 年前

    枚举非常有用,我一直在使用 Enum 要为不同语言的某些字段添加说明的内容很多,如以下示例所示:

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

    然后您可以根据传递给 getDescription(String lang) 方法,例如:

    String statusDescription = Status.valueOf("ACT").getDescription("en");
    
        25
  •  0
  •   John Hemming    8 年前

    我喜欢使用这种过程将命令作为字符串解析为枚举。我通常将其中一个枚举设置为“未知”,因此在未找到其他枚举时返回(即使是在不区分大小写的基础上),而不是空枚举(这意味着没有值)会有所帮助。因此我使用这种方法。

    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;
    }
    
        26
  •  0
  •   Bishal Jaiswal    5 年前

    获取枚举名称的最快方法是在应用程序启动时创建枚举文本和值的映射,并获取名称调用函数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());
        } 
    }