假设我有一个枚举
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显示了这两种方法。
你也应该小心处理你的案子。让我解释一下:Blah.valueOf(“A”)有效,但Blah.valueOf(“A”)无效。然后Blah.valueOf(“a”.toUpperCase(Locale.ENGLISH))也会起作用。
在Android上,你应该使用Locale.US,正如苏拉指出的那样。
下面是我使用的一个漂亮的实用程序:
/**
* 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。
如果文本与枚举值不同,则另一种解决方案:
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;
}
}
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;
}
另一种实现方法是使用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个示例
这里有一个方法可以对任何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()
));
}
如果您不想编写自己的实用程序,请使用Google的番石榴库:
Enums.getIfPresent(Blah.class, "A")
与内置Java函数不同,它让您检查Blah中是否存在A,并且不会引发异常。
这里有一个使用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();
}
}
为了补充前面的答案,并解决围绕空值和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的更多信息。
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”的调用名称。
您可能需要:
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”。
一种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;
}
}
Apache的commons-lang库有一个静态函数org.Apache.mons.lang3.EnumUtils.getEnum,它将字符串映射到Enum类型。基本上与杰弗里·郑的答案相同,但当它已经在野外时,不需要自己动手。
另一个实用程序以相反的方式捕获。使用标识该Enum的值,而不是从其名称。
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中唯一的公共方法,不是final方法,也不是静态方法。如果Foo在public、非final和非静态方法上有多个,例如,getTranslate返回“drei”,则可以使用另一个方法:EnumUtil.from(Foo.class,“drei”,“getTranslate”)。
使用Joshua Bloch《有效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示例
枚举类型中静态块的执行顺序
如何从Java枚举的String值查找它
我喜欢使用这种过程将命令作为字符串解析为枚举。我通常会将其中一个枚举设置为“未知”,因此当其他枚举未找到时(即使在不区分大小写的基础上)返回该枚举,而不是返回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;
}
在Michael Myers的回答中添加了一个有用的工具。。。
valueOf()在不喜欢其输入的情况下抛出两个不同的异常。
非法数据异常NullPointerEx选项
如果您的要求是这样的,那么您不能保证您的String一定会匹配枚举值,例如,如果String数据来自数据库并且可能包含旧版本的枚举,那么您需要经常处理这些。。。
所以这里有一个我编写的可重用方法,它允许我们定义一个默认的Enum,如果我们传递的String不匹配,则返回该Enum。
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
}
在Java8中,静态Map模式更容易,是我的首选方法。如果您想将Enum与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);
}
}
我的两分钱在这里:使用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 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();
}
}
Use:
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();
}
}
}
由于尚未提及交换机版本,我介绍了它(重用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)方法。
获取enum名称的最快方法是在应用程序启动时创建enum文本和值的映射,并调用函数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.name());
}
}
public static String getEnumName(String text) {
return map.get(text.toLowerCase());
}
}
枚举非常有用。我一直在使用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(Stringlang)方法的语言代码动态检索描述,例如:
String statusDescription = Status.valueOf("ACT").getDescription("en");
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.FALLACK),并避免空响应。您可以扩展特定枚举以使默认值为自动
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
我正在寻找一个答案来查找“blah”名称,而不是其值(而不是文本)。根据马努的回答,我发现这段代码很有用:
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;
}
}
枚举值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
}
}
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"));
}
}
使用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
public enum DivisionType {
DEFAULT(0){
@Override
public void sort(List<SigInUserDto> SigInUserDtos) {
SigInUserDtos.sort(new SigInUserCoinsQueueComparator());
}
},
ASSIGNPOINTS(1) {
@Override
public void sort(List<SigInUserDto> SigInUserDtos) {
SigInUserDtos.sort(new SigInUserPointsComparator());
}
},
ASSIGNEVENORDER(2) {
@Override
public void sort(List<SigInUserDto> SigInUserDtos) {
SigInUserDtos.sort(new SigInUserOrderCountComparator());
}
};
public final Integer label;
DivisionType(Integer label) {
this.label = label;
}
public static DivisionType getTypeById(Integer id) {
for (DivisionType value : DivisionType.values()) {
if (value.label == id) {
return value;
}
}
return DEFAULT;
}
public abstract void sort(List<SigInUserDto> SigInUserDtos);
}
使用枚举:DivisionType.getTypeById(object.getBalancingTypesId().intValue()).sort(sigInUserDtoList);
在这里,sort()函数在每个枚举匹配下实现(重载)。因此,基于对象“object.getBalancingTypesId().intValue()”匹配值,调用并排序特定的枚举匹配。