Java의 문자열 값에서 열거 형 값을 얻는 방법은 무엇입니까?


1984

그냥 열거 형이 있다고 가정 해보십시오.

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

내가 예를 들어, 문자열의 열거 값을 찾고자하는 "A"것이다 Blah.A. 어떻게 할 수 있을까요?

인가 Enum.valueOf()내가 필요로하는 방법은? 그렇다면 어떻게 사용합니까?

답변:


2258

예, Blah.valueOf("A")당신을 줄 것이다 Blah.A.

이름은 case :를 포함 하여 정확히 일치 해야 Blah.valueOf("a")하며 Blah.valueOf("A ")둘 다를 던집니다 IllegalArgumentException.

정적 방법 valueOf()과는 values()컴파일시에 생성 된 소스 코드에 표시되지 않습니다. 그러나 Javadoc에는 나타납니다. 예를 들어 Dialog.ModalityType두 방법을 모두 보여줍니다.


100
참고 로이 Blah.valueOf("A")방법은 대소 문자를 구분 하며 외부 공백을 허용하지 않으므로 @ JoséMi가 제안한 대체 솔루션입니다.
Brett

3
@ Michael Myers,이 답변은 지금까지 가장 많이 투표되었으므로 열거 형과 문자열 값을 정확히 동일하게 정의하는 것이 좋습니다.
케빈 메러디스

4
@ KevinMeredith : 당신이 toString()가치 를 의미한다면 , 아니오, 나는 그렇게 말하지 않을 것입니다. name()재정의하지 않는 한 열거 상수의 실제 정의 된 이름을 얻습니다.
Michael Myers

3
"컴파일 타임에 생성되고 소스 코드에 나타나지 않음"은 정확히 무엇을 의미합니까? ?
treesAreEverywhere

8
@treesAreEverywhere보다 구체적으로, 이러한 메소드는 컴파일러에 의해 생성 (또는 합성 )됩니다. 실제 enum Blah {...}정의는 자신의 valuesnor 을 선언하려고 시도해서는 안됩니다 valuesOf. "클래스"멤버 변수를 실제로 선언 한 적이 없어도 "AnyTypeName.class"를 작성하는 방법과 같습니다. 컴파일러는 모든 것이 제대로 작동하도록합니다. (이 답변은 3 개월 후 더 이상 유용하지 않을 수 있습니다.)
Ti Strga

864

텍스트가 열거 값과 동일하지 않은 경우 다른 해결책 :

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

396
throw new IllegalArgumentException("No constant with text " + text + " found")보다 낫다 return null.
위스키 시에라

8
@whiskeysierra Jon Skeet은 이에 동의하지 않습니다. stackoverflow.com/questions/1167982/…
이상현

11
@Sangdol null을 반환하는 것이 더 좋은 이유 알려주시겠습니까?
위스키 시라

57
@Sangdol은 보통 같은 상황에서 SUN이하는 일을 확인하는 것이 좋습니다. 등 Enum.valueOf ()는 이 도시되어 IS 이 경우에 예외를 발생하는 최상의 방법. 예외적 인 상황 이기 때문입니다. "성능 최적화"는 읽을 수없는 코드를 작성하는 나쁜 변명이다 ;-)
raudi

5
@Nullable 어노테이션을 사용하여 "읽을 수 있도록";-)
JoséMi

121

내가 사용하는 멋진 유틸리티는 다음과 같습니다.

/**
 * 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.valueOfT삭제됩니다.


176
그 빈 캐치 블록은 정말 미안합니다.
위스키 시에라

32
@LazloBonin : 예외는 예외적 인 상황이며 제어 흐름에는 적용되지 않습니다. 효과적인 Java 의 사본을 얻으십시오 .
복원 모니카

10
사용하려는 Java API에서 예외가 발생하고 코드에서 예외를 발생시키지 않으려면 이와 같이 예외를 삼키거나 처음부터 예외가 발생하지 않도록 논리를 처음부터 다시 작성할 수 있습니다. 예외를 삼키는 것은 종종 덜 악합니다.
Nate CK

47
끔찍 해요! 항상 처리 할 수있는 예외를 항상 잡아라. 위의 예는이 를 수행하지 않는 완벽한 예 입니다. 왜? 따라서 NULL을 반환하고 호출자는 NULL을 확인하거나 NPE를 throw해야합니다. 호출자가 상황을 처리하는 방법을 알고 있다면 if vs. try-catch를 수행하는 것이 조금 더 우아해 보일 수 있지만, 처리 할 수 ​​없으면 null을 다시 전달해야하고 호출자의 호출자 는 NULL을 다시 확인해야합니다 등 등
raudi

10
위의 솔루션을 공평하게하기 위해 실제로 IllegalArgumentException을 발생시키는 대신 null을 반환하고 프로그램 흐름을 중단 해야하는 경우가 있습니다 (예 : 항상 웹 서비스 스키마와 데이터베이스 스키마 사이의 열거 형 매핑). 일대일. 그러나 캐치 블록을 비워두면 안된다는 데 동의합니다. log.warn과 같은 코드 나 추적 목적으로 사용하십시오.
Adrian M

101

효과적인 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);
    }
}

참조 :

인스턴스의 Enum 및 Map을 사용하는 Oracle Java 예

Enum 타입에서 정적 블록의 실행 순서

문자열 값에서 Java 열거 형을 조회하는 방법


4
Joshua Bloch가 말한 경우 이것이 유일한 방법입니다 :-). 항상 아래로 스크롤해야한다는 수치입니다.
dermoritz

11
Java 8에서는 할 수있는 것처럼 훨씬 간단 Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity()))합니다 .toString () (생성자를 통해 전달됨)을 재정의하고 이름 대신에 대신 사용하는 것이 좋습니다. 특히 Enum이 직렬화 가능한 데이터와 연결되어있는 경우 제공하지 않고 케이싱을 제어 할 수 있습니다 수중 음파 탐지기.
Novaterata

1
Java 8은 분명히이 포럼에서 많은 (더 나은) 답변을 바꿀 수 있습니다. 꼬리 (Sonar)가 개 (응용 프로그램 코드)를 흔드는 것을 확신하지 못합니다.
Darrell Teague

3
unmodifiableMap어쨌든 그것을 넣으려고한다면 으로 시작하면 이점이 없습니다 ConcurrentHashMap. 를 사용하십시오 HashMap. (구아바가 있다면 ImmutableMap대신 추천합니다!)
Daniel Pryden

9
정적 초기화는 본질적으로 동기화 되므로 ConcurrentHashMap초기화 후에 맵이 수정되지 않는 여기서 사용할 이유 가 없습니다. 따라서 이유도 자체 JLS의 예를 예하는 것은 정기적를 사용합니다 HashMap.
Radiodef

74

또한 귀하의 경우에도주의를 기울여야합니다. 설명을 해 드리겠습니다 : Blah.valueOf("A")작동하지만 작동 Blah.valueOf("a")하지 않습니다. 그런 다음 다시 Blah.valueOf("a".toUpperCase(Locale.ENGLISH))작동합니다.

편집 tc 에 따라
변경 toUpperCase되었습니다 . 주석자바 문서toUpperCase(Locale.ENGLISH)

edit2 안드로이드 Locale.US에서는 sulai가 지적한 대로 사용해야합니다 .


6
기본 로케일에주의하십시오!
tc.

3
Android 사용자는 Android 설명서Locale.US 에서 기계가 읽을 수있는 입력 / 출력 사용을 명시 적으로 권장 한다는 점을 지적하고 싶습니다 .
sulai

2
@Trengot 네, 불행히도. 터키가 좋은 예입니다. 이것을 Java의 깨진 기본 문자 세트 처리 (유니 코드 대신 Windows에서 라틴어로 기본 설정)와 결합하면 문자 세트 또는 로케일을 허용하는 기본 버전의 메소드를 사용하는 것이 거의 안전하지 않습니다. 거의 항상 명시 적으로 정의해야합니다.
Stijn de Witt

Java의 "기본"문자 세트 등이 자체적으로 "단절"되었지만 확실하지는 않지만 대체 (언급 적으로 명시 적으로 수행되어야 함) 대신 UTF-8을 기본값으로 설정하면 일반적으로 이해하지 못하는 주니어 프로그래머에게 더 나은 시스템이 만들어집니다. 문자셋 개념.
Darrell Teague

38

다음은 모든 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
Stijn de Witt

대소 문자를 구분하지 않지만 키에 대한 (무작위) 문자열 할당보다 열거 형을 선호하지만 사소하지만 반복은 반복적 인 조회를 위해 성능이 떨어집니다. 따라서 EnumMap et al.
Darrell Teague

이 작동하지 않습니다! 내 목적을 위해 equalsIgnoreCase를 equals로 변경했습니다. 두 입력이 같더라도 코드가 실패했습니다.
MasterJoe2

36

사용하는 Blah.valueOf(string)것이 가장 좋지만 사용할 수도 있습니다 Enum.valueOf(Blah.class, string).


1
대소 문자 구분, 도움이되지 않음!
Murtaza Kanchwala

@MurtazaKanchwala 당신의 의견을 명확히 할 수 있습니까? 무엇을하려고합니까?
Peter Lawrey 2016 년

2
@PeterLawrey 님, 안녕하세요. String public enum ObjectType {PERSON ( "Person") public String parameterName에서 Enum을 가져 오려고했습니다. ObjectType (String parameterName) {this.parameterName = 매개 변수 이름; } 공개 문자열 getParameterName () {return this.parameterName; } public static ObjectType fromString (String parameterName) {if (parameterName! = null) {for (ObjectType objType : ObjectType.values ​​()) {if (parameterName.equalsIgnoreCase (objType.parameterName)) {return objType; }}} null을 반환합니다. }}
Murtaza Kanchwala 2016 년

34

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

이것이 어떻게 든 더 나은 대답인지 확실하지 않습니다. 이 경우 스트림은 모든 값에서 다른 것과 마찬가지로 단일 조회 반복자이며 맵 조회 impl보다 성능이 떨어집니다. 스트림은 예를 들어, 개행으로 분리 된 텍스트 파일의 병렬 실행이 성능을 향상시킬 수있는 다중 스레드 컨텍스트에서 더 가치가 있습니다.
Darrell Teague

28

자신의 유틸리티를 작성하지 않으려면 Google의 유틸리티를 사용하십시오. 도서관:

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

내장 Java 함수와 달리 A가 Blah에 있고 예외를 발생시키지 않는지 확인할 수 있습니다.


7
슬픈 부분은, 이것은 자바 선택이 아닌 자바 선택을 반환합니다
javaProgrammer

진실. 그러나 예상했다. Google과 Netflix에는 훌륭한 Java 라이브러리가 있습니다. 최신 버전으로 구현 된 Java 캐치 업 클래스와 겹치는 부분은 필연적으로 문제를 일으 킵니다. 하나의 공급 업체 라이브러리에 있어야합니다.
Darrell Teague

26

내 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 언어 자체의 이점을 얻을 수 있습니다. 예를 들면 다음과 같습니다.

  1. HeaderParam 주석에서 유형 직접 변환

1
더 읽기 쉬운 switch블록 을 작성하는 .orElse(null)대신 , 대신 .orElseThrow()예외 던지기를 코딩 할 수 있으며 default필요한 경우 더 유용한 정보를 포함 할 수 있습니다. 보다 융통성있게 사용할 수 있도록v -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())
Adam

또는 단지를 반환 Optional에서 findFirst()그가 원하는 경우 사용자가 결정할 수 있도록 .orElse(null), orElseThrow()또는 무엇 이건 ...
user85421

1
a를 선언하는 public static MyEnum valueOf(String)것은 실제로 컴파일 오류입니다. 암시 적으로 정의 된 것과 동일하므로 이전 버전의 답변이 실제로 더 좋습니다. ( jls , ideone )
Radiodef

내 옵션에서는 예외를 피하고 선택을 사용하는 것이 좋습니다. 그 옆에 null을 무효화하고 Optional도 대신 사용해야합니다.
Hans Schreuder

다시 말하지만, 코드가 적거나 좋을지라도 이러한 스트림 구현은 모든 값에 대한 반복자이며 맵 조회 (성능이 적음)입니다.
Darrell Teague

16

다음이 필요할 수 있습니다.

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"을 반환합니다.


13

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 가지 예


7
이것은 본질적으로 valueOf당신을 위해 무엇 을합니다. 이 정적 메소드는 예외 외의 다른 것을 제공하지 않습니다. 그런 다음 if / else 구문은 매우 위험합니다 ... 새로운 열거 상수를 추가하면이 방법이 변경없이 중단됩니다.
YoYo

대소 문자를 구분하지 않는 조회를 수행하기 위해 valueOf를 사용하는 방법 또는 예외를 피하고 대체 이름을 제공하기 위해 별칭을 사용하는 방법에 대한이 예를 고려하십시오. stackoverflow.com/a/12659023/744133
YoYo

2
name()정적이 아닙니다.
nrubin29

10

구아바 라이브러리를 사용하는 솔루션. 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();
   }
}

8

이전 답변에 추가하고 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


이것은 Enum이 클래스이므로 메소드로 대체 될 수 있고 메소드를 재정의 할 수 있다는 사실을 활용하여 관련 패턴과 Enum 내부의 Optional 사용에 대한 좋은 대답입니다. 메서드에서 반환 된 null은 해당 버그를 구성합니다 (Fluent 체인의 메서드 호출에서 알 수없는 위치의 NPE).
Darrell Teague

8

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

Jackson은 JSON (JavaScript Object Notation) 구현입니다. 원래 질문은 JSON과 관련이 없습니다.
Darrell Teague

JSON 부분은 문자열에서 Enum을 얻는 것이 기본적으로 역 직렬화 유형이며 JSON / Jackson이 아마도 가장 인기있는 직렬화 솔루션이기 때문에 당시에 내가 찾은 보너스 항목이었습니다.
Novaterata

이해 측면에서 알지만 중재 측면에서-OP의 질문에 대답하는 데 기여하지 않았으므로 컨텍스트를 설정하는 데 도움을 주려고했습니다 .JSON은 실제로 잭슨을 훌륭한 라이브러리로 사용하여 Java에서 객체를 정식 형식으로 변환하는 방법입니다.
Darrell Teague

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

: stackoverflow.com에서 질문에 답하고 질문에 가이드에 대해이 링크를 한 번 봐 걸릴 stackoverflow.com/faq
bakoyaro

1
JoséMi의 답변과 거의 동일합니다.
Rup

6

해시 맵을 이용하는 중고 코드 생성에서 영감을 얻은 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;
        }

}

0과 1 식별자는 필요하지 않습니다. Enum values ​​() 메서드는 코딩 된 순서대로 멤버를 반환합니다. 따라서 첫 번째 항목은 서수 0, 두 번째 항목 등입니다.
Darrell Teague

6

열거 형은 매우 유용 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");

1
Enum을 더 밀고있는 좋은 예입니다. Map에서 표준 정적 이름과 조회를 사용하여 언어 인코딩을 만들었지 만 여전히 논리적으로 동일한 논리 값에 대해 다른 태그가있는 열거 형을 갖는 좋은 예입니다.
Darrell Teague

5

이건 어떤가요?

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

4

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".


4

Apache의 commons-lang 라이브러리에는 정적 함수 org.apache.commons.lang3.EnumUtils.getEnum 이있어 문자열을 Enum 유형에 매핑합니다. 본질적으로 Geoffreys와 같은 대답이지만 이미 야생에있을 때 왜 자신을 굴리십시오.


1
공정한 의견 (DRY)이지만 ... 대부분의 Apache Commons 기능은 훌륭하지만 그 기반에서 몇 가지 버그와 안티 패턴을 발견했습니다. 따라서 Joshua Bloch의 구현은 더 강력한 기반이 될 수 있습니다. 그런 다음 Apache 코드를 검토하여 다른 사람이 무엇을 구현했는지 알아야합니다. Java 동시성을 다시 작성한 유명한 Doug Leah라는 말이 있으면 암시 적으로 신뢰할 것입니다.
Darrell Teague

4

유용한 유틸리티를 사용하여 최고 등급의 답변에 추가하는 중 ...

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
}

2

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).


1

또 다른 유틸리티는 반대로 캡처합니다. 이름이 아닌 해당 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").


1

코 틀린 솔루션

내선 번호를 만든 다음에 전화하십시오 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

당신의 대답이 더 나은 가정이 될 것이라고 생각하십니까? stackoverflow.com/questions/28548015/…
랍스터

0

이 종류의 프로세스를 사용하여 명령을 문자열로 열거하여 열거하는 것을 좋아합니다. 나는 일반적으로 열거 중 하나를 "알 수 없음"으로 표시하므로 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;
}

-1

열거 형의 이름을 얻는 가장 빠른 방법은 응용 프로그램이 시작될 때 열거 형 텍스트 및 값의 맵을 작성하고 이름을 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());
    } 
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.