활용 Java에서 문자열 값에서 열거 형 값을 가져 오는 방법은 무엇입니까?




java enum 활용 (20)

그냥 enum이 있다고 해봅시다.

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

문자열의 enum 값을 찾고 싶습니다. 예를 들어 "A"Blah.A 입니다. 이것을 어떻게 할 수 있습니까?

Enum.valueOf() 메서드가 필요한 것입니까? 그렇다면 어떻게 사용합니까?


다른 유틸리티는 역순으로 캡처합니다. 열거 형을 식별하는 값을 사용합니다. 열거 형의 이름이 아닙니다.

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 와 같이 public이 아닌 final 메소드가 아닌 경우, EnumUtil.from(Foo.class, "drei", "getTranslate") 과 같은 다른 메소드를 사용할 수 있습니다.


필자는 이러한 종류의 프로세스를 사용하여 문자열로 명령을 열거 형으로 구문 분석합니다. 나는 일반적으로 열거 형 중 하나를 "알 수 없음"으로 사용하므로 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의 암시 적 정적 메서드 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

영감 : 자바에서 열거 형의 예


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


switch 이 아직 언급되지 않았기 때문에 (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) , null 는 돌려 Enum.valueOf(String name) 지지 않는 형태로 IllegalArgumentException 하지 않고, Enum.valueOf(String name)contract 을 유지합니다. 따라서 이름이 null 이고 defaultValuenull 경우 default 경우 NullPointerException 을 던집니다. 그것이 valueOfOrDefault 작동하는 방식입니다.

이 접근법은 Java 8에서 Map.getOrDefault(Object key, V defaultValue) 메소드를 제공하는 Map Map.getOrDefault(Object key, V defaultValue) 의 설계를 채택합니다.


내 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 언어 자체에서 얻는 이점을 얻을 수 있습니다. 예 :

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

유용한 유틸리티와 함께 ​​최고 등급의 답변에 추가 ...

valueOf() 는 입력이 마음에 들지 않는 경우 두 개의 다른 예외를 throw합니다.

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

다음과 같이해야 할 수도 있습니다.

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

Stringified Enum 이름으로 값을 반환합니다. 예를 들어 fromEnumName에 "PERSON"을 입력하면 열거 형 값인 "Person"을 반환합니다.


텍스트가 열거 형 값과 다른 경우 다른 해결책은 다음과 같습니다.

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

아파치의 commons-lang 라이브러리는 String을 Enum 타입으로 매핑 할 정적 함수 org.apache.commons.lang3.EnumUtils.getEnum 가지고 있습니다. 본질적으로 Geoffreys와 같은 대답이지만, 이미 야생에있을 때 왜 자신의 것을 굴려 놓을까요?


Java 8에서는 정적 Map 패턴이 더 쉽고 내 선호하는 방법입니다. Enum with Jackson을 사용하려면 toString을 재정의하고 이름 대신 해당 이름을 사용하고 @JsonValue 로 주석을 @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);
    }
}

다음은 내가 사용하는 멋진 유틸리티입니다.

/**
 * 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 행을 변경하십시오.

TEnum.valueOf 따라 T.classEnum.valueOf 를 사용할 수 없다.


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


O (1) 메소드는 해시 맵 (hashmap)을 사용하는 저조한 생성 코드에서 영감을 얻었습니다.

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

}

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

java.lang.Enum 은 Java의 모든 열거 형에서 사용할 수있는 몇 가지 유용한 메서드 java.lang.Enum 정의합니다.

  • name() 메서드를 사용하여 열거 형 상수의 이름을 가져올 수 있습니다. 열거 형 상수를 쓰는 데 사용되는 문자열 리터럴은 해당 이름입니다.
  • 마찬가지로 values() 메서드를 사용하여 열거 형에서 모든 열거 형 상수의 배열을 가져올 수 있습니다.
  • 그리고 질문에 대해서는 아래와 같이 valueOf() 메서드를 사용하여 String을 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() 메서드는 "MALE" 을 반환하는 이름을 호출하는 Enum 상수 Gender.MALE을 반환합니다.


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

당신은 또한 당신의 사건에 조심해야합니다. Blah.valueOf("A") 는 작동하지만 Blah.valueOf("a") 는 작동하지 않습니다. 그런 다음 다시 Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) 가 작동합니다.

편집하다
tc를 기준으로 toUpperCase(Locale.ENGLISH) 변경되었습니다 . 주석 및 java 문서

edit2 android에서 sulai가 가리키는 대로 Locale.US 를 사용해야합니다.


자신의 유틸리티를 작성하고 싶지 않으면 Google의 guava 라이브러리를 사용하십시오.

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

내장 자바 함수와는 달리 A가 Blah에 존재하는지 확인하고 예외를 throw하지 않습니다.


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

참조 :

열거 형 및 인스턴스 맵을 사용한 Oracle Java 예제

열거 형에서 정적 블록의 실행 순서

String 값에서 Java enum을 어떻게 검색 할 수 있습니까?





enums