내가 열거 형을 가지고 있다고 가정 해보십시오.
public enum Blah { A, B, C, D }
그리고 문자열의 열거형 값을 찾고 싶습니다. 예를 들어 "A"
Blah.A
가 될 것입니다. 어떻게 이런 일이 가능할까요?
Enum.valueOf()
가 필요한 방법입니까? 그렇다면 이것을 어떻게 사용할까요?
질문자 :Malachi
내가 열거 형을 가지고 있다고 가정 해보십시오.
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
은 두 가지 방법을 모두 보여줍니다.
텍스트가 열거형 값과 동일하지 않은 경우 다른 솔루션:
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()); } }
또한 다음을 참조하십시오.
내가 사용하는 멋진 유틸리티는 다음과 같습니다.
/** * 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
가 지워 Enum.valueOf
T.class
에 T.class를 사용할 수 없다는 것이 너무 나쁩니다.
케이스도 조심해야 합니다. 설명하겠습니다. Blah.valueOf("A")
는 작동하지만 Blah.valueOf("a")
는 작동하지 않습니다. 그런 다음 다시 Blah.valueOf("a".toUpperCase(Locale.ENGLISH))
가 작동합니다.
Android에서는 sulai가 지적한 Locale.US
를 사용해야 합니다.
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(); } }
다음은 모든 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() )); }
Blah.valueOf(string)
것이 가장 Enum.valueOf(Blah.class, string)
를 사용할 수도 있습니다.
여기 내 두 센트 : 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 언어 자체에서 몇 가지 이점을 얻을 수 있습니다. 예를 들어:
자체 유틸리티를 작성하지 않으려면 Google의 구아바 라이브러리를 사용하세요.
Enums.getIfPresent(Blah.class, "A")
내장된 Java 함수와 달리 Blah에 A가 있고 예외를 throw하지 않는지 확인할 수 있습니다.
다음이 필요할 수 있습니다.
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"이 반환됩니다.
이를 수행하는 또 다른 방법은 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 BB
다음은 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(); } }
열거형은 매우 유용합니다. 다음 예제와 같이 다른 언어로 된 일부 필드에 대한 설명을 추가하기 위해 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 8에서는 정적 맵 패턴이 훨씬 더 쉽고 내가 선호하는 방법입니다. Jackson과 함께 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); } }
이전 답변에 추가하고 null 및 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을 방지하는 방법에 대한 추가 정보가 있습니다.
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; }
해시맵을 사용하는 Thrift 생성 코드에서 영감을 받은 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; } }
Apache의 commons-lang 라이브러리에는 String을 Enum 유형에 매핑하는 정적 함수 org.apache.commons.lang3.EnumUtils.getEnum이 있습니다. 본질적으로 Geoffrey Zheng's 와 동일한 답변이지만 이미 야생에 있을 때 자신을 굴릴 필요가 없습니다.
사용하다:
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.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"
를 반환합니다.
유용한 유틸리티와 함께 Michael Myers의 답변 에 추가 ...
valueOf()
는 입력이 마음에 들지 않는 경우 두 가지 다른 예외를 throw합니다.
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; } } }
기본값을 제공함으로써 null
이 반환되지 않는 방식으로 IllegalArgumentException
을 던지지 않고 Enum.valueOf(String name)
의 계약 을 유지합니다. 따라서 이름이 null
NullPointerException
을 throw하고 defaultValue
가 null
default
발생합니다. 이것이 valueOfOrDefault
작동하는 방식입니다.
이 접근 방식은 Java 8에서 Map.getOrDefault(Object key, V defaultValue)
메서드를 제공하는 Map
-Interface의 디자인을 채택합니다.
나는 그 값(텍스트가 아님)이 아닌 "blah" 이름을 찾기 위한 답을 찾고 있었습니다. Manu의 답변을 기반으로 이 코드가 유용하다는 것을 알았습니다.
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; }
}
역방향으로 캡처하는 또 다른 유틸리티입니다. 이름이 아닌 해당 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에서 최종적이지 않고 정적 메소드가 아닌 고유한 공개입니다. getTranslate
와 같이 최종 및 정적 메서드가 아닌 public 이상의 메서드가 있는 경우 다른 메서드를 사용할 수 있습니다. EnumUtil.from(Foo.class, "drei", "getTranslate")
.
열거형 값()
열거형 클래스는 컴파일될 때 클래스의 정적 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 } }
나는 이러한 종류의 프로세스를 사용하여 명령을 문자열로 열거형으로 구문 분석하는 것을 좋아합니다. 나는 일반적으로 열거형 중 하나를 "알 수 없음"으로 가지고 있으므로 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; }
확장을 만든 다음 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 } }
또는 둘 다 원하면 두 번째를 만드십시오.
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
열거형의 이름을 얻는 가장 빠른 방법은 응용 프로그램이 시작될 때 열거형 텍스트와 값의 맵을 만들고 이름을 얻으려면 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")
는 찾고 있는 문이지만 이것은 CASE SENSITIVE 이므로 Blah.valueOf("a")가 작동하지 않고 예외를 생성한다는 점을 명심하십시오.
출처 : http:www.stackoverflow.com/questions/604424/how-to-get-an-enum-value-from-a-string-value-in-java
임의의 정수를 어떻게 생성합니까? (0) | 2021.12.01 |
---|---|
Android에서 '컨텍스트'란 무엇입니까? (0) | 2021.11.30 |
Git을 사용하여 이전 커밋에서 분기 (0) | 2021.11.30 |
복사 및 교환 관용구는 무엇입니까? (0) | 2021.11.30 |
Git 관리 프로젝트의 모든 로컬 변경 사항을 이전 상태로 되돌리려면 어떻게 해야 합니까? (0) | 2021.11.30 |