Как получить значение перечисления из строкового значения в Java? - PullRequest
1812 голосов
/ 03 марта 2009

Скажем, у меня есть перечисление, которое просто

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

и я хотел бы найти значение перечисления строки, например "A", которое будет Blah.A. Как можно было бы сделать это?

Является ли Enum.valueOf() метод, который мне нужен? Если так, как бы я использовал это?

Ответы [ 25 ]

2 голосов
/ 30 декабря 2017

А как же?

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();
        }
    }
}
1 голос
/ 02 августа 2018

Поскольку 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.

1 голос
/ 24 февраля 2016

Еще одна утилита захвата в обратном направлении. Использование значения, которое идентифицирует этот 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", который является уникальным public, не final и не статическим методом в Foo. В случае, если Foo имеет более чем открытый, не конечный и не статический метод, например, getTranslate, который возвращает «drei», можно использовать другой метод: EnumUtil.from(Foo.class, "drei", "getTranslate").

0 голосов
/ 16 апреля 2019

Самый быстрый способ получить имя 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.toString());
        }
    }
    public static String getEnumName(String text) {
        return map.get(text.toLowerCase());
    } 
}
0 голосов
/ 30 августа 2016

Мне нравится использовать этот процесс для анализа команд как строк в перечислениях. У меня обычно одно из перечислений как «неизвестное», поэтому полезно возвращать его, когда другие не найдены (даже без учета регистра), а не ноль (это означает, что значения нет). Поэтому я использую этот подход.

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...