検索 - java enum 逆引き




どのようにJavaの文字列値から列挙型の値を取得するには? (16)

Apacheのcommons-langライブラリには、StringをEnum型にマップする静的関数org.apache.commons.lang3.EnumUtils.getEnumあります。 本質的にGeoffreysと同じ答えですが、なぜ野生の中にすでに存在しているのでしょうか?

私はちょうど列挙型を持っていると言う

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

文字列の列挙型の値、たとえば"A"これはBlah.AたいとBlah.Aます。 どのようにこれを行うことが可能でしょうか?

Enum.valueOf()メソッドが必要ですか? もしそうなら、私はこれをどのように使うのでしょうか?


Enumの暗黙の静的メソッドname()を使用してこれを行う別の方法。 nameは、指定された文字列をチェックするために使用できるenumを作成するために使用された正確な文字列を返します。

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での列挙の例


Java 8では、静的なMapパターンはさらに簡単で、私の好みの方法です。 Enum with Jacksonを使用する場合は、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);
    }
}

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

}

Blah.valueOf(string)を使うのが一番良いですが、 Enum.valueOf(Blah.class, string)も使うことができます。


あなたはこれを必要とするかもしれません:

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("A")動作しますが、 Blah.valueOf("a")は動作しません。 その後、再びBlah.valueOf("a".toUpperCase(Locale.ENGLISH))が動作します。

編集
tcに基づいてtoUpperCase(Locale.ENGLISH)変更されました。 コメントとjavaドキュメント

edit2アンドロイドでは、あなたが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行を変更してEnum.valueOf

Tが消去されるとT.classEnum.valueOfを使用することはできません。


このようなプロセスを使用して、コマンドを文字列として列挙して解析するのが好きです。 私は通常、 "未知"として列挙の1つを持っているので、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を与えます。

大文字と小文字を区別しない名前であることに注意してくださいBlah.valueOf("a")Blah.valueOf("A ")どちらもIllegalArgumentExceptionスローします。

静的メソッドvalueOf()およびvalues()はコンパイル時に作成され、ソースコードには表示されません。 彼らはJavadocに登場する。 たとえば、 Dialog.ModalityTypeは両方のメソッドを示します。


テキストが列挙値と同じでない場合の別の解決策:

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

便利なユーティリティを使用して、最高評価の回答に追加...

valueOf()は、入力が気に入らない場合に2つの異なる例外をスローします。

  • IllegalArgumentException
  • NullPointerExeption

文字列データがデータベースから来て、古いバージョンの列挙型を含む場合など、文字列が列挙型の値と完全に一致することが保証されない要件がある場合は、これらを処理する必要がありますしばしば...

だからここで私が書いた再利用可能なメソッドは、私たちが渡す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
}

独自のユーティリティを作成したくない場合は、Googleのguavaライブラリを使用してください:

Enums.getIfPresent(Blah.class, "A")

組み込みのJava関数とは異なり、AがBlahに存在し、例外をスローしないかどうかをチェックします。


私はそれを紹介しています(OPのenumを再利用しています)。

  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(String name)メソッドに追加の値を与えないので、異なる振る舞いをしたい場合は、追加のメソッドを定義することだけが意味を持ちます。 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(String name) contractを維持し、 IllegalArgumentExceptionをスローせずに、 nullを返さないようにしnull 。 したがって、名前がnull場合はNullPointerExceptionをスローし、 defaultValuenull場合はdefault場合はdefaultValueをスローしnull 。 これがvalueOfOrDefault働きです。

このアプローチでは、 Map -Interfaceの設計が採用されています。これは、Java 8のMap.getOrDefault(Object key, V defaultValue)メソッドを提供します。


逆の方法で別のユーティリティをキャプチャします。 名前からではなく、列挙型を識別する値を使用する。

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")は、 getValueを使用して "drei"に一致するため、 Foo.THREE返します。 Fooが "drei"を返すgetTranslateように、最終的ではなく静的メソッドではなく、公開されている場合、 EnumUtil.from(Foo.class, "drei", "getTranslate")という別のメソッドを使用できます。





enums