ChatGPT解决这个技术问题 Extra ChatGPT

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

说我有一个枚举,它只是

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

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

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


M
Michael Myers

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

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

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


作为参考,Blah.valueOf("A") 方法是区分大小写 并且不允许多余的空格,因此@JoséMi 在下面提出了替代解决方案。
@Michael Myers,由于这个答案是迄今为止投票最多的,我是否应该理解将枚举及其字符串值定义为完全相同的好习惯?
@KevinMeredith:如果您的意思是 toString() 值,不,我不会这么说。 name() 将为您提供枚举常量的实际定义名称,除非您覆盖它。
“在编译时创建并且不出现在源代码中”究竟是什么意思。 ?
@treesAreEverywhere 更具体地说,这些方法由编译器生成(或synthesized)。实际的 enum Blah {...} 定义不应尝试声明自己的 valuesvaluesOf。这就像您如何编写“AnyTypeName.class”,即使您从未真正声明过“类”成员变量;编译器使这一切都可以正常工作。 (此答案可能在 3 个月后对您不再有用,但以防万一。)
P
Peter Mortensen

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

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

throw new IllegalArgumentException("No constant with text " + text + " found") 会比 return null 更好。
@Sangdol 通常检查 SUN - 哎呀 - Oracle 在相同情况下所做的事情是一件好事。正如 Enum.valueOf() 所展示的那样,IS 是在这种情况下抛出异常的最佳实践。 因为这是一种特殊情况。 “性能优化”是编写不可读代码的糟糕借口;-)
P
Peter Mortensen

使用来自 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().toLowerCase(),instance);
        }
        ENUM_MAP = Collections.unmodifiableMap(map);
    }

    public static MyEnum get (String name) {
        return ENUM_MAP.get(name.toLowerCase());
    }
}

另见:

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


这在 Java 8 中甚至更简单,因为您可以这样做:Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))我还建议覆盖 toString()(通过构造函数传入)并使用它而不是名称,特别是如果 Enum 与可序列化数据相关联,因为这可以让您控制套管没有给声纳一个合适的。
Static initialization is inherently synchronized,因此绝对没有理由在此处使用 ConcurrentHashMap,因为在初始化后地图永远不会被修改。因此,甚至例如 JLS 中的示例本身也使用常规 HashMap
P
Peter Mortensen

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

/**
 * 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 用于 Enum.valueOf,因为 T 已被删除。


那个空的 catch 块真的让我发疯了,对不起。
@LazloBonin:异常是针对异常情况,而不是针对控制流。为自己获取一份 Effective Java
可怕!始终,始终捕获可以处理的异常。上面的例子是一个如何不做的完美例子。为什么?所以它返回 NULL,然后调用者必须检查 NULL 或抛出 NPE。如果调用者知道如何处理这种情况,那么执行 if 与 try-catch 可能看起来更优雅,但如果他无法处理,他必须再次传递 null 并且调用者的调用者必须再次检查 NULL等等等等。
@whiskeysierra 我知道对 Java 或软件开发充满热情是一回事,但你得冷静一下。像这样出人头地/成为额外的人没有任何好处。
返回 Optional 而不是 nullable 怎么样?
P
Peter Mortensen

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

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


请注意默认语言环境!
H
Hans Schreuder

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

Java 8 做了一些好事,虽然我喜欢 Streams(主要用于并发)......这实际上不是使用它们的理由。它什么都不买 OP 并且性能更差......只需将所有项目的 for/next 循环替换为相同的 Stream 版本(甚至不是并行)。对于一些条目......谁在乎但要清楚,这不是一些“因为Java 8而更好”的例子。它只是返回 Optional vs null 的流利风格的绿色与蓝色“不同”实现(并且流利风格需要所有连接方法的非空返回)。
R
Radiodef

这是一种可以对任何 Enum 执行此操作的方法,并且不区分大小写。

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

很好地使用泛型,但不确定 IllegalArgumentException 是否真的是正确的合同。首先,查找失败完全有可能(并且预期?)......它本身不在集合中(实际上是枚举)。抛出 RuntimeException “在方法外传播 [s]”。由于这不在方法签名中 - 调用者不会期望它。最好使用 Map 构造(在未找到时返回 null)或者甚至更好... Optional.empty()。
P
Peter Mortensen

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


P
Peter Mortensen

我的两分钱:使用 Java 8 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 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 语言本身获得一些好处;例如:

在 HeaderParam 注解处直接转换类型


P
Peter Mortensen

如果您不想编写自己的实用程序,请使用 Google 的 库:

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

与内置的 Java 函数不同,它让您检查 A 是否存在于 Blah 中并且不会引发异常。


P
Peter Mortensen

您可能需要这样做:

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

    ObjectType(String parameterName) {
        this.parameterName = parameterName;
    }

    public String getParameterName() {
        return this.parameterName;
    }

    // From the String method, it 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”。


P
Peter Mortensen

另一种方法是使用 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


m
marc_s

在 Java 8 中,静态 Map 模式更加简单,是我的首选方法。如果您想将枚举与杰克逊一起使用,您可以覆盖 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);
    }
}

混淆代码大赛亚军?我的意思是这在技术上是正确的。 :-) ...但是对于 Map 上的简单 for/next 循环来说,它是非常迟钝的——可以说,这并不比 Java 的早期版本所能提供的更好。 private static final Map MAP = Stream.of(MyEnumForJson.values()).collect(Collectors.toMap(Object::toString, Function.identity()));
我认为当你习惯于 for 循环时,流看起来很迟钝,但对于每个循环来说,它们都是自己的
P
Peter Mortensen

这是使用 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();
   }
}

P
Peter Mortensen

枚举非常有用。我一直在使用 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");

P
Peter Mortensen

为了补充之前的答案,并解决一些关于 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 的更多信息。


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

P
Peter Mortensen

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

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

类似地,可以使用 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,并在其上调用名称返回 "MALE"


P
Peter Mortensen

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

}

P
Peter Mortensen

Apache 的 commons-lang 库有一个静态函数 org.apache.commons.lang3.EnumUtils.getEnum,它将一个 String 映射到您的 Enum 类型。基本上与 Geoffrey Zheng's 的答案相同,但是当它已经在野外时,没有任何必要推出自己的答案。


P
Peter Mortensen

利用:

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

P
Peter Mortensen

使用有用的实用程序添加到 Michael Myers' answer...

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

IllegalArgumentException

空指针异常

如果您的要求无法保证您的 String 一定会匹配枚举值,例如,如果 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
}

P
Peter Mortensen

枚举 valueOf()

枚举类在编译时会自动获取类中的静态 valueOf() 方法。 valueOf() 方法可用于获取给定 String 值的枚举类的实例。

例如:

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Strings.TWO.name());
    }
    enum Strings {
        ONE, TWO, THREE
    }
}

L
LuCio

由于尚未提及 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;
      }
    }
  }

通过提供默认值,我们保留了 Enum.valueOf(String name)contract 而不会以在任何情况下都不会返回 null 的方式抛出 IllegalArgumentException。因此,如果名称是 null,我们会抛出 NullPointerException,如果 defaultValuenull,我们会抛出 default。这就是 valueOfOrDefault 的工作原理。

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


P
Peter Mortensen

我正在寻找一个答案来找到“blah”名称而不是它的值(不是文本)。基于 Manu's answer,我发现此代码很有用:

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 valueOfCode(String blahCode) throws IllegalArgumentException {
    Blah blah = Arrays.stream(Blah.values())
            .filter(val -> val.name().equals(blahCode))
            .findFirst()
            .orElseThrow(() -> new IllegalArgumentException("Unable to resolve blah: " + blahCode));

    return blah;
}

}


M
Moesio

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

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 有多个 public、not final 和 not static 方法,例如返回“drei”的 getTranslate,则可以使用其他方法:EnumUtil.from(Foo.class, "drei", "getTranslate")


S
Swapnil Gangrade
public enum ToggleStatusUpdate {
    OFF("off", 1),
    ON("on", 2);
    
    private final String name;
    private final int position;
    
    private ToggleStatusUpdate(String name, int position) {
        this.name = name;
        this.position = position;
    }

    public String getName() {
        return name;
    }

    public int getPosition() {
        return position;
    }
    
    public static int getPositionForName(String name) {
        for(ToggleStatusUpdate toggleStatusUpdate : ToggleStatusUpdate.values()) {
            if (toggleStatusUpdate.getName().equals(name)) {
                return toggleStatusUpdate.getPosition();
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        System.out.println(ToggleStatusUpdate.getPositionForName("off"));
    }
}

A
And-y

使用 Streams 的 Java 8 答案和评论的组合。它使用默认值创建一个静态 Map 进行查找,以防止空检查。

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

    private static final Map<String, Blah> ENUM_MAP = Stream.of(Blah.values())
            .collect(Collectors.toMap(Enum::name, Function.identity()));

    public static Blah of(final String name) {
        return ENUM_MAP.getOrDefault(name, INVALID);
    }
}

// e.g.
Blah.of("A");
A

Blah.of("X")
INVALID

J
John Hemming

我喜欢使用这种过程将命令作为字符串解析为枚举。我通常将其中一个枚举设为“未知”,因此在未找到其他枚举(即使在不区分大小写的情况下)而不是 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;
}

G
Gibolt

Kotlin 解决方案

创建扩展程序,然后调用 valueOf<MyEnum>("value")。如果类型无效,你会得到 null 并且必须处理它

inline fun <reified T : Enum<T>> valueOf(type: String): T? {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        null
    }
}

或者,您可以设置默认值、调用 valueOf<MyEnum>("value", MyEnum.FALLBACK) 并避免空响应。您可以扩展您的特定枚举以使默认值为自动

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
    return try {
        java.lang.Enum.valueOf(T::class.java, type)
    } catch (e: Exception) {
        default
    }
}

或者如果你想要两者,做第二个:

inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default