답변:
예, Blah.valueOf("A")
당신을 줄 것이다 Blah.A
.
이름은 case :를 포함 하여 정확히 일치 해야 Blah.valueOf("a")
하며 Blah.valueOf("A ")
둘 다를 던집니다 IllegalArgumentException
.
정적 방법 valueOf()
과는 values()
컴파일시에 생성 된 소스 코드에 표시되지 않습니다. 그러나 Javadoc에는 나타납니다. 예를 들어 Dialog.ModalityType
두 방법을 모두 보여줍니다.
toString()
가치 를 의미한다면 , 아니오, 나는 그렇게 말하지 않을 것입니다. name()
재정의하지 않는 한 열거 상수의 실제 정의 된 이름을 얻습니다.
enum Blah {...}
정의는 자신의 values
nor 을 선언하려고 시도해서는 안됩니다 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
삭제됩니다.
효과적인 Java : Joshua Bloch의 패턴을 사용하십시오 .
(간단하게 단순화)
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()))
합니다 .toString () (생성자를 통해 전달됨)을 재정의하고 이름 대신에 대신 사용하는 것이 좋습니다. 특히 Enum이 직렬화 가능한 데이터와 연결되어있는 경우 제공하지 않고 케이싱을 제어 할 수 있습니다 수중 음파 탐지기.
unmodifiableMap
어쨌든 그것을 넣으려고한다면 으로 시작하면 이점이 없습니다 ConcurrentHashMap
. 를 사용하십시오 HashMap
. (구아바가 있다면 ImmutableMap
대신 추천합니다!)
ConcurrentHashMap
초기화 후에 맵이 수정되지 않는 여기서 사용할 이유 가 없습니다. 따라서 이유도 자체 JLS의 예를 예하는 것은 정기적를 사용합니다 HashMap
.
또한 귀하의 경우에도주의를 기울여야합니다. 설명을 해 드리겠습니다 : Blah.valueOf("A")
작동하지만 작동 Blah.valueOf("a")
하지 않습니다. 그런 다음 다시 Blah.valueOf("a".toUpperCase(Locale.ENGLISH))
작동합니다.
편집 tc 에 따라
변경 toUpperCase
되었습니다 . 주석 과 자바 문서toUpperCase(Locale.ENGLISH)
edit2
안드로이드 Locale.US
에서는 sulai가 지적한 대로 사용해야합니다 .
Locale.US
에서 기계가 읽을 수있는 입력 / 출력 사용을 명시 적으로 권장 한다는 점을 지적하고 싶습니다 .
다음은 모든 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 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 언어 자체의 이점을 얻을 수 있습니다. 예를 들면 다음과 같습니다.
switch
블록 을 작성하는 .orElse(null)
대신 , 대신 .orElseThrow()
예외 던지기를 코딩 할 수 있으며 default
필요한 경우 더 유용한 정보를 포함 할 수 있습니다. 보다 융통성있게 사용할 수 있도록v -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())
Optional
에서 findFirst()
그가 원하는 경우 사용자가 결정할 수 있도록 .orElse(null)
, orElseThrow()
또는 무엇 이건 ...
다음이 필요할 수 있습니다.
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"을 반환합니다.
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의 Enum의 10 가지 예
valueOf
당신을 위해 무엇 을합니다. 이 정적 메소드는 예외 외의 다른 것을 제공하지 않습니다. 그런 다음 if / else 구문은 매우 위험합니다 ... 새로운 열거 상수를 추가하면이 방법이 변경없이 중단됩니다.
name()
정적이 아닙니다.
구아바 라이브러리를 사용하는 솔루션. 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();
}
}
이전 답변에 추가하고 null 및 NPE와 관련된 토론 중 일부를 해결하기 위해 구아바 옵션을 사용하여 부재 / 무효 사례를 처리합니다. 이것은 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에서는 정적 맵 패턴이 훨씬 쉽고 선호되는 방법입니다. 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);
}
}
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
합니다. 다음 예제와 같이 다른 언어로 일부 필드에 대한 설명을 추가하기 위해 많은 것을 사용 했습니다.
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 라이브러리에는 정적 함수 org.apache.commons.lang3.EnumUtils.getEnum 이있어 문자열을 Enum 유형에 매핑합니다. 본질적으로 Geoffreys와 같은 대답이지만 이미 야생에있을 때 왜 자신을 굴리십시오.
유용한 유틸리티를 사용하여 최고 등급의 답변에 추가하는 중 ...
valueOf()
입력이 마음에 들지 않으면 두 가지 다른 예외가 발생합니다.
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
}
A와 switch
-version 언급 아직 내가 소개되지 않은 (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
작동 하는 방식입니다.
이 접근법 은 Java 8 Map
에서 메소드를 제공하는 -Interface 의 디자인을 채택합니다 Map.getOrDefault(Object key, V defaultValue)
.
또 다른 유틸리티는 반대로 캡처합니다. 이름이 아닌 해당 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의 정적 메소드가 아닌 최종 공개가 아닌 고유 한 공개 "drei"와 일치 Foo.THREE
시키는 데 사용 getValue
되므로을 리턴합니다 . Foo가 getTranslate
"drei"를 반환하는 것과 같이 정적이 아닌 정적 메서드가 아닌 공용 메서드를 초과하는 경우 다른 메서드를 사용할 수 있습니다 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
}
}
또는 둘 다 원하는 경우 두 번째를 만드십시오.
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
이 종류의 프로세스를 사용하여 명령을 문자열로 열거하여 열거하는 것을 좋아합니다. 나는 일반적으로 열거 중 하나를 "알 수 없음"으로 표시하므로 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.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가 제안한 대체 솔루션입니다.