java枚举字符串 - java枚举序列化




通过字符串值查找Java枚举 (16)

假设我有一个枚举

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

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

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



O(1)方法的灵感来源于使用散列映射的节俭生成代码。

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

}

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

/**
 * 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被删除。


为了增加前面的答案,并解决一些关于nulls和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();
        }
    }
}

对于那些不知道的,这里有一些关于避免null与可选的更多信息: https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional : https://code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional


你可能需要这样做:

public enum ObjectType {
    PERSON("Person");

    public String parameterName;

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

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

    //From String method 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”


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


使用番石榴图书馆的解决方案。 方法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 MyEnum {
    FIRST,
    SECOND,
    THIRD;

    public static Optional<MyEnum> fromString(String value){
        try{
            return Optional.of(MyEnum.valueOf(value));
        }catch(Exception e){
            return Optional.empty();
        }
    }
}

在Java 8中,静态的Map模式更容易,是我的优先方法。 如果你想用Jackson的Enum,你可以重写toString并使用它来代替name,然后用@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 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 fromText(String text) {
        return Arrays.stream(values())
          .filter(bl -> bl.text.equalsIgnoreCase(text))
          .findFirst()
          .orElse(null);
    }
}

如果文本与枚举值不相同,则为另一种解决方案:

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

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

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

请注意,名称必须完全匹配,包括case: Blah.valueOf("a")Blah.valueOf("A ")都会抛出IllegalArgumentException

静态方法valueOf()values()是在编译时创建的,并不出现在源代码中。 尽管如此,它们确实出现在Javadoc中; 例如, Dialog.ModalityType显示两种方法。


添加到最高评分的答案,一个有用的实用程序...

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

  • IllegalArgumentException
  • NullPointerExeption

如果你的需求是这样的,你不能保证你的字符串肯定会匹配一个枚举值,例如,如果字符串数据来自数据库并且可能包含旧版本的枚举,那么你需要处理这些经常...

所以这里是我写的一个可重用的方法,它允许我们定义一个默认的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
}

通过使用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个例子


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




enums