回答:
はい、Blah.valueOf("A")
与えますBlah.A
。
名前がなければならないことに注意正確な:ケースを含め、試合Blah.valueOf("a")
とBlah.valueOf("A ")
両方投げますIllegalArgumentException
。
静的メソッドvalueOf()
とvalues()
はコンパイル時に作成され、ソースコードには表示されません。ただし、Javadocには表示されます。たとえば、Dialog.ModalityType
両方の方法を示しています。
toString()
値を意味するなら、いいえ、私はそれを言っていません。name()
オーバーライドしない限り、列挙定数の実際に定義された名前を取得します。
enum Blah {...}
定義は、それ自体をvalues
も宣言しようとするべきではありませんvaluesOf
。「クラス」メンバー変数を実際に宣言したことがなくても、「AnyTypeName.class」を書き込む方法に似ています。コンパイラーはすべてを正しく動作させます。(この回答は、3か月後には役に立たなくなる可能性がありますが、
テキストが列挙値と同じでない場合の別の解決策:
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;
}
}
throw new IllegalArgumentException("No constant with text " + text + " found")
より良いでしょうreturn null
。
これが私が使う気の利いたユーティリティです:
/**
* 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
消去されます。
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(),instance);
}
ENUM_MAP = Collections.unmodifiableMap(map);
}
public static MyEnum get (String name) {
return ENUM_MAP.get(name);
}
}
こちらもご覧ください:
Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))
特にEnumがシリアル化可能なデータに関連付けられている場合、これを使用せずに大文字と小文字を制御できるため、toString()(コンストラクタを通じて渡される)をオーバーライドし、名前の代わりに使用することをお勧めしますソナーフィット。
unmodifiableMap
とにかくそれを置くつもりなら、それから始めることには何の利益もありませんConcurrentHashMap
。だけを使用してくださいHashMap
。(もしあなたがグアバを持っているならImmutableMap
、私は代わりにそれをお勧めします!)
ConcurrentHashMap
ここで使用する理由はまったくありません。初期化後にマップが変更されることはありません。したがって、なぜJLS自体の例でも通常のを使用するのでしょうかHashMap
。
ケースにも注意が必要です。説明させてください:うまくBlah.valueOf("A")
いくが、Blah.valueOf("a")
うまくいきません。またBlah.valueOf("a".toUpperCase(Locale.ENGLISH))
動作します。
編集tcに基づいてに
変更toUpperCase
さtoUpperCase(Locale.ENGLISH)
れました。コメントとJavaドキュメント
edit2 sulaiが指摘する
ようにLocale.US
、Android では使用する必要があります。
これは、任意の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()
));
}
equalsIgnoreCase
方法です。+1
使用するのBlah.valueOf(string)
が最適ですが、使用することもできますEnum.valueOf(Blah.class, string)
。
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();
}
}
独自のユーティリティを作成したくない場合は、Googleの グアバ 図書館:
Enums.getIfPresent(Blah.class, "A")
組み込みのJava関数とは異なり、AがBlahに存在し、例外をスローしないかどうかを確認できます。
ここで私の2セント:Java8ストリームの使用+正確な文字列のチェック:
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言語自体からいくつかの利点が得られます。例えば:
switch
ブロックを記述できるようにする.orElse(null)
代わり.orElseThrow()
に、default
句に例外スローをコーディングして、必要に応じてより役立つ情報を含めることができます。そして、それをより寛大に使うためにv -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())
Optional
からfindFirst()
、彼が望んでいる場合は、ユーザーが決定できるように、.orElse(null)
、orElseThrow()
または何...
public static MyEnum valueOf(String)
暗黙的に定義されたものと同じであるため、実際にはコンパイルエラーです。したがって、古いバージョンの回答の方が実際には優れています。(jls、ideone)
これが必要になる場合があります:
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;
}
}
もう1つ追加:
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」を指定すると、列挙型の値、つまり「Person」が返されます。
name()
Enumの暗黙の静的メソッドを使用してこれを行う別の方法。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の列挙型の10の例
valueOf
にあなたのために何をします。この静的メソッドは、特別なものや例外などを提供しません。その場合、if / else構文は非常に危険です。新しい列挙型定数が追加されると、このメソッドは変更せずに中断します。
name()
静的ではありません。
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 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();
}
}
}
気付いていない人のために、以下はOptionalでnullを回避する方法の詳細です:https : //code.google.com/p/guava-libraries/wiki/UsingAndAvoidingNullExplained#Optional
Java 8では、静的なMapパターンがさらに簡単になり、私の優先メソッドです。ジャクソンでEnumを使用したい場合は、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);
}
}
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;
}
ハッシュマップを使用するリサイクル生成コードから発想を得た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;
}
}
Enumは非常に便利です。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(String lang)
メソッドに渡された言語コードに基づいて動的に説明を取得できます。次に例を示します。
String statusDescription = Status.valueOf("ACT").getDescription("en");
java.lang.Enum
Javaのすべての列挙型で使用できるいくつかの便利なメソッドを定義します。
name()
メソッドを使用して、任意のEnum定数の名前を取得できます。列挙型定数の記述に使用される文字列リテラルは、その名前です。values()
メソッドを使用して、Enum型からすべてのEnum定数の配列を取得できます。valueOf()
以下に示すように、Javaで任意の文字列を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"
。
Apacheのcommons-langライブラリには、StringをEnumタイプにマップする静的関数org.apache.commons.lang3.EnumUtils.getEnumがあります。本質的にジェフリーズと同じ答えですが、それがすでに実際に出回っているのに、なぜあなた自身のロールをするのですか?
役立つユーティリティを使用して、最高評価の回答に追加します...
valueOf()
入力が気に入らない場合は、2つの異なる例外をスローします。
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
}
- switch
バージョンはまだ言及されていないので、紹介します(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(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)
IllegalArgumentException
null
NullPointerException
null
default
defaultValue
null
valueOfOrDefault
このアプローチMap
は、Map.getOrDefault(Object key, V defaultValue)
Java 8以降のメソッドを提供する-Interface の設計を採用しています。
逆の方法でキャプチャする別のユーティリティ。名前からではなく、その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
固有の公開、Fooのではない最後のではなく、静的メソッドである「DREI」を、一致します。Fooに、getTranslate
「drei」を返すような、finalメソッドやstaticメソッド以外のパブリックメソッドがある場合、他のメソッドを使用できますEnumUtil.from(Foo.class, "drei", "getTranslate")
。
拡張機能を作成して、を呼び出します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.FALLBACK)
、null応答を回避することもできます。特定の列挙型を拡張して、デフォルトを自動にすることができます
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
}
}
または、両方が必要な場合は、2番目を作成します。
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
この種類のプロセスを使用して、コマンドを文字列として列挙に解析します。私は通常、列挙の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;
}
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());
}
}
Blah.valueOf("A")
メソッドは大文字と小文字を区別し、無関係な空白を許容しないため、@JoséMiが以下で提案する代替ソリューションを使用します。