假设我有一个枚举类型,内容如下:
public enum Blah {
A, B, C, D
}
我想要根据一个字符串找到对应的枚举值,例如 "A"
对应的是 Blah.A
。有什么方法可以实现吗?
Enum.valueOf()
是我需要的方法吗?如果是,我该如何使用它?
假设我有一个枚举类型,内容如下:
public enum Blah {
A, B, C, D
}
我想要根据一个字符串找到对应的枚举值,例如 "A"
对应的是 Blah.A
。有什么方法可以实现吗?
Enum.valueOf()
是我需要的方法吗?如果是,我该如何使用它?
是的,Blah.valueOf("A")
将会返回 Blah.A
。
请注意名称必须精确匹配,包括大小写: Blah.valueOf("a")
和 Blah.valueOf("A ")
都会抛出一个 IllegalArgumentException
异常。
valueOf()
和 values()
这两个静态方法是在编译时创建的,不会出现在源代码中。但是它们会在 Javadoc 中出现,例如,Dialog.ModalityType
显示了这两个方法。
toString()
的值,我不会这么说。除非您覆盖它,否则name()
将为您获取枚举常量的实际定义名称。 - Michael Myersenum Blah {...}
定义不应该尝试声明自己的 values
或 valuesOf
。这就像你可以写 "AnyTypeName.class" 一样,即使你从未声明过一个 "class" 成员变量;编译器会让它所有的东西都正常工作。(这个答案可能在3个月后对您已经没有用了,但以防万一。) - Ti Strga如果文本与枚举值不相同,另一个解决方案是:
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;
}
}
使用来自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());
}
}
另请参见:
Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))
。我还建议覆盖toString()(通过构造函数传递),并使用它来代替name,特别是如果枚举与可序列化数据相关联,因为这样可以让您控制大小写而不会引起Sonar的问题。 - Novaterataprivate val mapStringToEnum by lazy { values().associateBy { it.name } }
fun get(name: String): MyEnum? {
return mapStringToEnum[name]
}
- Jordan Stewart这是我使用的一个很棒的工具:
/**
* 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
被擦除了。在处理大小写时需要注意,让我解释一下:执行Blah.valueOf("A")
是可以的,但是 Blah.valueOf("a")
就无法正常工作。不过,Blah.valueOf("a".toUpperCase(Locale.ENGLISH))
可以正常工作。
在 Android 上,应该使用Locale.US
,正如 sulai 指出的那样。
在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();
}
}
/**
* 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()
));
}
我这里提供一个建议:使用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语言本身获得一些好处;例如:
使用Blah.valueOf(string)
是最好的方法,但你也可以使用Enum.valueOf(Blah.class, string)
。
如果您不想编写自己的工具程序,可以使用Google的guava库:
Enums.getIfPresent(Blah.class, "A")
与内置的Java函数不同,它允许您检查A是否存在于Blah中,而不会抛出异常。