假设我有一个枚举

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

我想找到一个字符串的枚举值,例如“a”,它将是Blah.a。如何做到这一点?

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


当前回答

为了补充前面的答案,并解决围绕空值和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();
        }
    }
}

对于那些不知道的人,这里有一些关于使用Optional避免null的更多信息。

其他回答

使用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

枚举值Of()

枚举类在编译时自动获取类中的静态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
    }
}

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

灵感:Java中Enum的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;
}

然后在我的enum类中,我通常使用这个来保存一些类型:

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

如果枚举不是全部大写,只需更改Enum.valueOf行。

太糟糕了,因为t被删除,我不能对Enum.valueOf使用t.class。

由于尚未提及交换机版本,我介绍了它(重用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(Stringname)方法提供任何附加值,因此只有在我们希望具有不同行为的情况下,才有必要定义一个附加方法。如果我们不想引发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(字符串名称)的约定,而不会以任何情况下都不会返回null的方式抛出IllegalArgumentException。因此,如果名称为null,我们将抛出NullPointerException,如果默认值为null,则抛出NullPointerException。这就是valueOfOrDefault的工作原理。

该方法采用了Map接口的设计,该接口提供了Java 8中的Map.getOrDefault(Object key,V defaultValue)方法。