假设我有一个枚举

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

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

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


当前回答

由于尚未提及交换机版本,我介绍了它(重用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)方法。

其他回答

我的两分钱在这里:使用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注释处直接转换类型

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

可以使用name()方法获取任何Enum常量的名称。用于编写枚举常量的字符串文字是它们的名称。类似地,values()方法可用于从Enum类型获取所有Enum常量的数组。对于所问的问题,您可以使用valueOf()方法在Java中将任何String转换为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”的调用名称。

这里有一个使用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();
   }
}
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 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。