Как получить значение перечисления из строкового значения в Java

avatar
Malachi
2 марта 2009 в 22:56
1303498
32
2154

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

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

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

Нужен ли мне Enum.valueOf() метод? Если да, то как мне это использовать?

Источник

Ответы (32)

avatar
Michael Myers
2 марта 2009 в 22:57
2441

Да, Blah.valueOf("A") даст вам Blah.A.

Обратите внимание, что имя должно быть точным соответствием , включая регистр: Blah.valueOf("a") и Blah.valueOf("A ") оба вызывают IllegalArgumentException.

Статические методы valueOf() и values() создаются во время компиляции и не отображаются в исходном коде. Однако они действительно появляются в Javadoc; например, Dialog.ModalityType показывает оба метода.

Brett
17 декабря 2013 в 17:37
108

Для справки, метод Blah.valueOf("A") чувствителен к регистру и не допускает посторонних пробелов, поэтому @ JoséMi ниже предлагает альтернативное решение.

Kevin Meredith
12 февраля 2014 в 21:24
3

@Michael Myers, поскольку этот ответ получил наибольшее количество голосов, должен ли я понимать, что это хорошая практика, чтобы определить перечисление и его значение String, чтобы они были точно такими же?

Michael Myers♦
14 февраля 2014 в 04:10
4

@KevinMeredith: Если вы имеете в виду значение toString(), нет, я бы этого не сказал. name() предоставит вам фактическое определенное имя константы перечисления, если вы не переопределите его.

treesAreEverywhere
7 марта 2014 в 00:43
4

Что именно вы имеете в виду под словами «создаются во время компиляции и не отображаются в исходном коде». ?

Ti Strga
30 мая 2014 в 19:31
8

@treesAreEverywhere В частности, эти методы сгенерированы (или синтезированы ) компилятором. Фактическое определение enum Blah {...} не должно пытаться объявлять собственное values или valuesOf. Это похоже на то, как вы можете написать AnyTypeName.class, даже если вы на самом деле никогда не объявляли переменную-член «class»; компилятор заставляет все это просто работать. (Этот ответ может больше не быть вам полезен через 3 месяца, но на всякий случай.)

Bill K
19 ноября 2015 в 17:39
1

Отличный ответ - кроме того, я обнаружил, что добавление нескольких небольших вспомогательных методов к перечислениям очень помогает ... Например, если вы создаете статическую карту записей в нижнем регистре в конструкторе, вы можете добавить метод, который выглядит перечисление без учета регистра или преобразование подчеркивания в пробелы, чтобы пользовательский ввод, такой как «Вторая запись», мог отображаться в перечисление SECOND_ENTRY.

nemetroid
29 июня 2017 в 08:54
0

Почему за комментарий @Brett так много голосов? Конечно, он чувствителен к регистру и не допускает лишних пробелов, все остальное было бы безумием.

maaartinus
21 августа 2018 в 22:48
0

@nemetroid Не то, чтобы безумие, учитывая, что пробелы в именах не допускаются и что все имена перечислений являются uppecase по соглашению. Таким образом, возможен толерантный метод поиска, поскольку результат остается уникальным. Однако пользователям может потребоваться что-то еще более терпимое, и поэтому лучше всего предоставить каноническую строгую версию (и есть другие проблемы, такие как верхний регистр, чувствительный к языку и тому подобное).

Bex
22 августа 2018 в 14:27
1

Проголосуйте за, но этот пост был бы еще лучше с упоминанием Enum :: name

Artanis Zeratul
9 марта 2021 в 00:27
0

В моем случае это не работает, я все еще получаю исключение IllegalArgumentException.

Michael Myers♦
9 марта 2021 в 14:28
0

@ArtanisZeratul: Похоже, это не точное совпадение с учетом регистра.

avatar
And-y
1 февраля 2022 в 16:42
0

Комбинация ответов и комментариев для Java 8 с использованием Streams. Он создает статическую карту для поиска с возможностью значения по умолчанию, чтобы предотвратить проверки на null.

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

    private static final Map<String, Blah> ENUM_MAP = Stream.of(Blah.values())
            .collect(Collectors.toMap(Enum::name, Function.identity()));

    public static Blah of(final String name) {
        return ENUM_MAP.getOrDefault(name, INVALID);
    }
}

// e.g.
Blah.of("A");
A

Blah.of("X")
INVALID
avatar
Swapnil Gangrade
19 августа 2021 в 12:00
1
public enum ToggleStatusUpdate {
    OFF("off", 1),
    ON("on", 2);
    
    private final String name;
    private final int position;
    
    private ToggleStatusUpdate(String name, int position) {
        this.name = name;
        this.position = position;
    }

    public String getName() {
        return name;
    }

    public int getPosition() {
        return position;
    }
    
    public static int getPositionForName(String name) {
        for(ToggleStatusUpdate toggleStatusUpdate : ToggleStatusUpdate.values()) {
            if (toggleStatusUpdate.getName().equals(name)) {
                return toggleStatusUpdate.getPosition();
            }
        }
        return -1;
    }

    public static void main(String[] args) {
        System.out.println(ToggleStatusUpdate.getPositionForName("off"));
    }
}
avatar
Numan Gillani
8 июля 2021 в 14:02
0

Blah.valueOf("A") - это утверждение, которое вы ищете, но имейте в виду, что это ЧУВСТВИТЕЛЬНО К ДЕЛУ , поэтому Blah.valueOf ("a") не будет работать и вызовет исключение.

avatar
Nitya Nand Pandey
5 марта 2021 в 06:46
1

Enum valueOf ()

Класс перечисления автоматически получает статический метод valueOf () в классе при компиляции. Метод valueOf () можно использовать для получения экземпляра класса enum для заданного значения String.

Например:

public class Main {
    public static void main(String[] args) throws Exception {
        System.out.println(Strings.TWO.name());
    }
    enum Strings {
        ONE, TWO, THREE
    }
}
Peter Mortensen
10 августа 2021 в 18:13
0

Откуда кое-что из этого скопировано? Из сообщения блога Javagyansite? (Хотя это тоже могло быть плагиатом.)

avatar
orly.sharon
29 декабря 2020 в 11:18
2

Я искал ответ, чтобы найти имя "бла", а не его значение (не текст). Основываясь на ответе Ману, я считаю этот код полезным:

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

}

Peter Mortensen
10 августа 2021 в 18:09
0

Я не думаю, что это даже компилируется (выделение синтаксиса также дает подсказку).

avatar
Gibolt
18 января 2020 в 00:08
0

Решение Kotlin

Создайте добавочный номер, а затем позвоните по номеру 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) и избегая нулевого ответа. Вы можете расширить свое конкретное перечисление, чтобы значение по умолчанию было автоматическим

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
nabster
5 мая 2020 в 22:39
0

Как вы думаете, ваш ответ будет здесь лучше? coderhelper.com/questions/28548015/…

shinzou
18 июня 2020 в 10:29
1

Это не вопрос Котлина.

Gibolt
18 июня 2020 в 16:06
1

Это похоже на Js / jQuery. Когда разработчики Android ищут решение, они ищут Java, а затем переводят на Kotlin. Это неочевидное, лучшее решение, чем прямой перевод. Поисковые системы не собираются в ближайшее время отказываться от этого решения, лучше просто помочь разработчикам быстро найти хорошее решение. Он отмечен как Kotlin, разработчики Java могут просто пропустить

avatar
Ebraheem Alrabeea
23 июня 2019 в 08:44
8

Enum очень полезен. Я много использовал 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");
Darrell Teague
15 апреля 2020 в 22:11
1

Хороший пример с продвижением Enums дальше. Сделал бы языковую кодировку с использованием стандартных статических имен и поиска на карте, но все же ... хороший пример наличия перечисления с разными тегами для того, что по сути является одним и тем же логическим значением.

avatar
Bishal Jaiswal
16 апреля 2019 в 13:25
0

Самый быстрый способ получить имя перечисления - создать карту текста и значений перечисления при запуске приложения, а для получения имени вызвать функцию 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());
    }
}
avatar
LuCio
2 августа 2018 в 19:57
3

Поскольку версия 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.

Peter Mortensen
10 августа 2021 в 18:04
0

switch и ООП?

LuCio
11 августа 2021 в 06:12
0

@PeterMortensen: Вопрос OP не ограничивается ООП. Имеется в виду Java.

avatar
DCO
30 декабря 2017 в 07:38
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();
        }
    }
}
avatar
Hans Schreuder
1 августа 2017 в 10:17
47

В Java 8 или новее с использованием потоков:

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();
    }
}
Darrell Teague
15 апреля 2020 в 22:03
0

Не уверен, что это лучший ответ. Потоки в этом случае представляют собой однопоточный итератор, как и любой другой по всем значениям, и, возможно, менее производительны, чем имплицит поиска по карте. Потоки имеют большее значение в многопоточном контексте, где, например, параллельное выполнение текстового файла, разделенного новой строкой, может повысить производительность.

Flaom
15 января 2021 в 20:59
0

@DarrellTeague Если вы измеряете разницу в наносекундах между решением Streams и решением поиска по карте, вы увидите разницу. Однако я считаю, что в реальном мире заметной разницы в производительности не будет, если только у вас нет довольно большого перечисления, что, на мой взгляд, является исключением из правила. Кроме того, подход Streams компактен и удобочитаем, хотя я уверен, что вы могли бы привести тот же аргумент для реализации карты.

avatar
Manu
13 июля 2017 в 13:38
32

Мои два цента: использование потоков Java 8 и проверка точной строки:

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
Adam
10 мая 2018 в 11:35
1

В качестве альтернативы, чтобы позволить вам писать более читаемые блоки switch, вы можете .orElse(null) вместо .orElseThrow(), чтобы вы могли закодировать выброс исключения в предложении default - и при необходимости включить более полезную информацию. И чтобы сделать его более мягким, вы можете использовать v -> Objects.equals(v.name, s == null ? "" : s.trim().toUpperCase())

user85421
2 августа 2018 в 20:58
0

или просто верните Optional из findFirst(), позволяя пользователю решить, хочет ли он .orElse(null), orElseThrow() или что-то еще ....

Radiodef
23 декабря 2018 в 23:34
1

Объявление public static MyEnum valueOf(String) на самом деле является ошибкой компиляции, поскольку она такая же, как и неявно определенная, поэтому более старая версия вашего ответа на самом деле лучше. (jls, идеон)

Hans Schreuder
23 мая 2019 в 10:57
0

В моем варианте лучше избегать исключений и использовать Optional. Рядом с этим мы должны аннулировать null и вместо этого использовать Optional.

Darrell Teague
15 апреля 2020 в 22:05
0

Опять же, просто помните, что даже если код выглядит хуже или лучше ... такая реализация Stream - это просто итератор по всем значениям, а не поиск по карте (менее эффективный).

avatar
Novaterata
27 апреля 2017 в 17:10
9

В Java 8 шаблон статической карты еще проще, и я предпочитаю его. Если вы хотите использовать 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);
    }
}
Darrell Teague
15 апреля 2020 в 22:06
0

Джексон - это реализация JSON (JavaScript Object Notation). Исходный вопрос не имел ничего общего с JSON.

Novaterata
16 апреля 2020 в 01:38
0

Часть JSON была просто бонусом, который я считал актуальным в то время, поскольку получение Enum из строки в основном является типом десериализации, а JSON / Jackson, вероятно, является самым популярным решением для сериализации.

Darrell Teague
17 апреля 2020 в 12:50
0

Поймите, но с точки зрения модерации - это не способствовало ответу на вопрос OP, поэтому просто пытаюсь помочь установить там контекст. JSON действительно является способом преобразования объектов в каноническую форму в Java, а Джексон - отличная библиотека.

avatar
lance.dolan
26 января 2017 в 20:30
4

Добавление к ответу Майкла Майерса с помощью полезной утилиты ...

valueOf() выдает два разных исключения в случаях, когда ему не нравится его ввод.

  • 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
}
avatar
John Hemming
30 августа 2016 в 09:11
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;
}
Peter Mortensen
10 августа 2021 в 17:58
0

Что он должен делать? Как это работает? В чем суть / идея? Ответьте, отредактировав (изменив) свой ответ, а не здесь, в комментариях ( без «Изменить:», «Обновить:» или аналогичный - ответ должен выглядеть так, как если бы он был написан сегодня).

avatar
Darrell Teague
15 июня 2016 в 16:37
133

Используйте шаблон из Джошуа Блоха, Эффективная 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());
    }
}

См. Также:

Пример Oracle Java с использованием Enum и Map экземпляров

Порядок выполнения статических блоков в типе Enum

Как мне найти перечисление Java по его строковому значению

dermoritz
10 января 2017 в 09:51
6

если это сказал Джошуа Блох, то это единственный выход :-). Жалко, что мне всегда приходится прокручивать здесь вниз.

Novaterata
27 апреля 2017 в 17:01
14

В Java 8 это еще проще, чем вы: Stream.of(MyEnum.values()).collect(toMap(Enum::name, identity())) Я также рекомендую переопределить toString () (переданный через конструктор) и использовать его вместо имени, особенно если Enum связан с сериализуемыми данными, поскольку это позволяет вам контролировать кожух, не давая Sonar подгонки.

Darrell Teague
28 апреля 2017 в 20:31
1

Java 8, безусловно, может / изменит многие (лучшие) ответы на этом форуме. Не уверен, что когда-нибудь хвост (сонар) виляет собакой (код приложения).

Daniel Pryden
8 марта 2018 в 16:13
4

Если вы все равно собираетесь поместить его в unmodifiableMap, то начинать с ConcurrentHashMap бесполезно. Просто используйте HashMap. (Если у вас есть ImmutableMap Гуавы, я бы рекомендовал это вместо этого!)

Darrell Teague
9 марта 2018 в 16:47
0

ImmutableMap от Google, безусловно, является лучшей (истинно глубоко неизменяемой) реализацией, но с целью демонстрации решения только для ядра Java ... и сосредоточения внимания на случае поиска по карте String использовались только классы ядра Java. В общем, было обнаружено, что ConcurrentHashMap почти всегда предпочтительнее, чем HashMap, учитывая общий профиль производительности (добавление, удаление, изменение) и простоту по сравнению с упаковкой / блокировкой HashMap, когда необходимо учитывать одновременное изменение.

Radiodef
5 августа 2018 в 17:24
11

Статическая инициализация по своей сути синхронизирована, поэтому нет абсолютно никаких причин использовать здесь ConcurrentHashMap, где карта никогда не изменяется после инициализации. Следовательно, почему даже, например, в самом примере JLS используется обычный HashMap.

Darrell Teague
24 августа 2018 в 16:48
0

Комментарий в коде явно заявляет, что "подойдет любая карта impl". Для младших разработчиков было обнаружено, что использование ConcurrentHashMap в качестве общей практики предпочтительнее в обмене с общими источниками ошибок и отказом от синхронизации модификаций карты в целом.

YoYo
29 августа 2018 в 15:28
1

@DarrellTeague - Если мы находимся в многопоточной среде, то обязательно подумайте о последствиях нашего выбора. Защитное использование синхронизированных коллекций без раздумий противоречит причинам, по которым у нас вообще есть параллелизм. Я не понимаю, почему коллекция, которая в принципе должна быть неизменяемой, может выиграть от реализации в виде параллельной коллекции.

Darrell Teague
31 августа 2018 в 01:28
0

@YoYo - опять же, как указано, подойдет любая карта impl, и на самом деле нет никаких последствий, положительных или отрицательных для данного impl. Пожалуйста, прочтите предыдущий комментарий о младших разработчиках, так что, учитывая все обстоятельства, учитывая, что ConcurrentHashMap не имеет потери производительности чтения, имеет применимость в качестве карты общего назначения impl, обычно над HashMap, где разработчики должны очень тщательно продумывать синхронизацию во время Обновить. Таким образом, здесь, где ConcurrentHashMap может использоваться без последствий, а может потребоваться в других случаях, когда требуется синхронизация - это кажется вполне разумным.

YoYo
31 августа 2018 в 02:15
1

Если вы твердо верите в это, я также должен посоветовать использовать synchronized (map) { ENUM_MAP = Collections.unmodifiableMap(map); }, чтобы избежать недетерминированного поведения в возможном итераторе, используемом внутри метода для создания неизменяемой версии - в качестве стандарта, чтобы младший разработчик не думал о много о тех же последствиях. См. Синхронизированные оболочки.

Darrell Teague
31 августа 2018 в 17:06
0

Спасибо @YoYo, и это хороший фрагмент impl в контексте для других, чтобы понять последствия получения доступа к итераторам во время создания / обновления карт - тонкий и трудный для отладки случай.

Enerccio
23 мая 2019 в 08:21
1

извините, но ConcurrentHashMap там совершенно бесполезен

hfontanez
11 сентября 2019 в 20:24
0

Я бы использовал Streams и вернул бы перечисление NullObject, если значение не существует. Возврат null почти всегда хуже, чем выброс исключения.

Darrell Teague
2 апреля 2020 в 20:33
0

Согласитесь, что общие контракты из Java для многих методов, возвращающих null, не предпочтительнее, чем возвращение Optional, особенно в свете разработки стиля Fluent. Однако это более новая конструкция. Тем не менее, если спросить «существует ли это значение» - не уверен, что имеет смысл возвращать Optional вместо null, что явно указывает на отсутствие такого значения, например, в вызове Map.get (), в котором отсутствует ключ.

Darrell Teague
2 апреля 2020 в 20:38
0

Чтобы завершить все это обсуждение «зачем использовать ConcurrentHashMap, если он вам не нужен» ... здесь нет ошибки. Более того, никакого влияния на производительность нет. Результат точно такой же, как и с любым другим (ненулевым значением) Map impl. Аргумент «но вам это не нужно» понятен, но если можно получить автомобиль с такой же топливной экономичностью, мощностью и т. Д. По той же цене, что и модель более низкого качества, почему бы не купить автомобиль более высокого качества, даже если ни один из (лучше) фичи используются?

Darrell Teague
30 декабря 2020 в 22:29
0

Добавлена ​​нечувствительность к регистру при поиске. Обратите внимание, что значение, возвращаемое функцией "getName ()", по-прежнему возвращает любое введенное исходное значение. Следует положить конец обсуждению поиска без учета регистра как тривиальной модификации реализации.

avatar
Moesio
24 февраля 2016 в 11:23
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.THREE, потому что он будет использовать getValue для соответствия «drei», который является уникальным общедоступным, а не конечным и не статическим методом в Foo. В случае, если у Foo больше, чем в общедоступном, не окончательном и не статическом методе, например, getTranslate, который возвращает «drei», можно использовать другой метод: EnumUtil.from(Foo.class, "drei", "getTranslate").

avatar
pjklauser
22 октября 2015 в 06:46
5

Библиотека Apache commons-lang имеет статическую функцию org.apache.commons.lang3.EnumUtils.getEnum, которая сопоставляет строку с вашим типом Enum. Тот же ответ, что и Джеффри Чжэна, но нет необходимости катить свой собственный, когда он уже находится в дикой природе.

Darrell Teague
15 апреля 2020 в 22:16
1

Справедливый комментарий (СУХОЙ), но ... хотя большая часть материала Apache Commons великолепна, я сам обнаружил несколько ошибок и антипаттернов в этой базе. Таким образом, можно сказать, что реализация Джошуа Блоха может иметь более прочную основу. Переходим к тому, чтобы просмотреть код Apache, чтобы узнать, что кто-то реализовал. Если бы, скажем, знаменитый Дуг Лиа переписал параллелизм в Java ... тогда я бы безоговорочно ему доверял.

Peter Mortensen
10 августа 2021 в 17:53
0

Первая ссылка не работает: «Не найдено. Запрошенный URL не найден на этом сервере».

avatar
Sisyphus
23 сентября 2015 в 09:08
6

Метод O (1), основанный на сгенерированном коде Thrift, который использует хэш-карту.

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

}
Darrell Teague
15 апреля 2020 в 22:13
1

Обратите внимание, что идентификаторы ноль (0) и один (1) не нужны. Метод Enum values ​​() вернет элементы в том же порядке, в котором они были закодированы. Таким образом, первая запись будет иметь порядковый номер ноль, вторая и т. Д.

avatar
Murtaza Kanchwala
2 июля 2015 в 11:54
16

Вам может понадобиться это:

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

Это вернет вам значение в виде строкового имени перечисления. Например, если вы укажете «PERSON» в fromEnumName, он вернет вам значение Enum, то есть «Person».

avatar
KNU
29 октября 2014 в 12:22
4

java.lang.Enum определяет несколько полезных методов, доступных для всех типов перечисления в Java:

  • Вы можете использовать метод name(), чтобы получить имя любой константы Enum. Строковый литерал, используемый для записи констант перечисления, - это их имя.
  • Аналогично, метод values() можно использовать для получения массива всех констант Enum из типа Enum.
  • И для заданного вопроса вы можете использовать метод valueOf() для преобразования любой String в константу Enum в Java, как показано ниже.
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".

avatar
tom
10 октября 2014 в 10:10
8

Чтобы добавить к предыдущим ответам и рассмотреть некоторые обсуждения вокруг нулей и NPE Я использую Guava Опции для обработки отсутствующих / недопустимых случаев . Это отлично подходит для анализа 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();
        }
    }
}

Для тех, кто не в курсе, вот дополнительная информация об избежании null с помощью Необязательно .

Darrell Teague
15 апреля 2020 в 22:09
0

Это действительно хороший ответ для связанных шаблонов и использования Optional внутри Enum - используя тот факт, что Enums также являются классами и, таким образом, могут быть украшены методами, методами переопределения и т. Д. Это хороший случай для программирования в стиле Fluent, поскольку Нулевые значения, возвращаемые методами, делают эту конструкцию ошибочной (NPE в неизвестных местах в цепочках вызовов методов Fluent).

avatar
javabrew
22 августа 2014 в 20:07
11

Вот решение, использующее библиотеки 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();
   }
}
Priidu Neemre
11 марта 2021 в 07:56
0

А как насчет Плутона ?!

avatar
Andrejs
2 апреля 2014 в 20:12
29

Если вы не хотите писать свою собственную утилиту, используйте библиотеку Google guava:

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

В отличие от встроенной функции Java, она позволяет вам проверить, присутствует ли A в Blah, и не вызывает исключения.

javaProgrammer
19 августа 2016 в 00:02
7

печальная часть, это возвращает google Optional, а не java Optional

Darrell Teague
13 августа 2018 в 17:30
0

Истинный. Тем не менее, Exoected. У Google и Netflix есть отличные библиотеки Java. Если есть перекрытие с классами догоняющего развития Java, реализованными в более новых версиях, неизбежно возникают проблемы. Вроде бы все на одной библиотеке поставщика.

avatar
Patrick Arnesen
1 декабря 2011 в 21:53
39

Вот метод, который может сделать это для любого 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()
    ));
}
Stijn de Witt
26 июля 2015 в 13:35
1

Этот вариант делает это правильно: equalsIgnoreCase - лучший вариант. +1

Darrell Teague
13 августа 2018 в 17:26
0

Подобно нечувствительности к регистру, но ... предпочитают перечисления вместо (случайных) строковых назначений для ключей и ... второстепенных, но итерация менее эффективна для такого, возможно, повторяющегося поиска. Следовательно, согласно EnumMap et al.

MasterJoe
26 ноября 2018 в 20:49
0

Это не работает ! Я изменил equalsIgnoreCase на equals для моей цели. Код не удался, несмотря на то, что оба входа равны были совершенно одинаковыми.

avatar
Vikram
29 ноября 2011 в 05:02
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

Вдохновение: 10 примеров Enum в Java

YoYo
30 сентября 2012 в 18:01
7

По сути, это то, что valueOf делает для вас. Этот статический метод не предлагает ничего лишнего, исключение и все такое. Тогда конструкции if / else очень опасны ... любая добавленная новая константа перечисления приведет к тому, что этот метод сломается без изменений.

YoYo
30 сентября 2012 в 18:18
0

Рассмотрим также этот пример того, как мы можем использовать valueOf для поиска без учета регистра или как мы можем избежать исключения и использовать псевдонимы для предоставления альтернативных имен: coderhelper.com/a/12659023/744133

nrubin29
21 апреля 2014 в 00:39
2

name() не статичен.

avatar
Prasobh.Kollattu
9 ноября 2011 в 09:50
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;
}
bakoyaro
9 ноября 2011 в 18:15
1

Взгляните на эту ссылку, чтобы узнать, как отвечать и задавать вопросы на coderhelper.com: coderhelper.com/faq

Rup
14 ноября 2011 в 12:40
2

Это более или менее похоже на ответ ХосеМи

Peter Mortensen
10 августа 2021 в 17:39
0

Объяснение было бы в порядке. Ответьте, отредактировав (изменив) свой ответ, а не здесь, в комментариях ( без «Изменить:», «Обновить:» или аналогичный - ответ должен выглядеть так, как если бы он был написан сегодня).

avatar
JoséMi
3 июня 2010 в 10:57
945

Другое решение, если текст не совпадает со значением перечисления:

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;
    }
}
whiskeysierra
31 июля 2010 в 10:28
433

throw new IllegalArgumentException("No constant with text " + text + " found") будет лучше, чем return null.

Sanghyun Lee
5 сентября 2011 в 04:06
8

@whiskeysierra Джон Скит не согласился бы с этим. coderhelper.com/questions/1167982/…

whiskeysierra
29 сентября 2011 в 15:04
14

@Sangdol Может ли вы просветить нас, почему возвращать null лучше?

whiskeysierra
29 сентября 2011 в 21:44
2

Этот комментарий относится к предлагаемому ответу на фактический перехват исключения, чтобы определить, представляет ли строка допустимое значение перечисления. Вам, вероятно, понадобится второй метод (например, isValid) для такого случая использования.

raudi
2 февраля 2012 в 07:43
63

@Sangdol обычно полезно проверить, что SUN - ой - Oracle делает в той же ситуации. И поскольку Enum.valueOf () показывает, что IS лучшая практика для создания исключения в этом случае. Потому что это исключительная ситуация. «Оптимизация производительности» - плохой предлог для написания нечитаемого кода ;-)

JoséMi
3 февраля 2012 в 08:20
5

Ну, вы также можете использовать аннотацию @Nullable, чтобы сделать ее «читаемой» ;-)

YoYo
30 сентября 2012 в 18:22
0

Хорошо, чтобы преобразовать строку в константу перечисления, вероятно, полезно выбросить исключение в случае нуля или отсутствия совпадения, как это делает valueOf. Однако подумайте, как бы вы реализовали метод проверки того, используется ли строка константами перечисления ... Пример, чтобы обойти все это на coderhelper.com/a/12659023/744133

Christophe Roussy
8 ноября 2012 в 10:29
3

Что касается обработки ошибок, это всегда зависит от источника информации. Если ваши значения поступают из внешнего источника (пользовательский ввод ...), которым вы не можете управлять, перехватите ошибку и покажите какое-нибудь значимое сообщение, если это возможно. В случае, если значение, переданное в valueOf, исходит из вашего собственного внутреннего кода, вы должны отловить ошибки и выйти из строя (журнал и сбой), вероятно, у вас есть ошибка, и ее можно исправить.

Jan Tacci
24 марта 2013 в 04:33
0

У меня действительно глупый вопрос ... в вашем методе fromString сразу после того, как вы выполняете equalsIgnoreCase , у вас есть b.text. Текст является закрытым членом класса перечисления, как вы можете получить к нему доступ?

JoséMi
27 марта 2013 в 06:16
0

@Jan: потому что сам код находится внутри класса enum и, конечно же, он имеет видимость всех атрибутов и методов этого класса.

Tyzoid
24 мая 2013 в 14:05
1

@raudi В этом случае я предпочитаю null, потому что, когда я иду за значением, я считаю более прагматичным проверять if(returnval == null), чем ловить исключение. Идеалистически это работает лучше: имеет ли смысл возвращать пустой результат, если он не совпадает? или выкинуть ошибку? Думаю, имеет смысл возвращать пустой результат.

raudi
27 мая 2013 в 17:05
2

@Tyzoid: Я не сказал, что это неправильно, я даже не сказал, что это плохая практика, я просто сказал, что выброс исключения выглядит более подходящим. Подумайте, что должен сделать вызывающий: если возвращается null, то возвращаемое значение необходимо проверять после каждого вызова, если вы не хотите поймать NPE, чего не следует ;-). Теперь посмотрим, что происходит, если генерируется исключение: вызывающий может решить, на каком уровне он хочет его перехватить: глобально перехватить исключение, глобально перехватить конкретное исключение или перехватить конкретное исключение при одиночных вызовах или любой их комбинации. Конечно, намного приятнее использовать ...

trutheality
29 мая 2013 в 21:45
5

@Tyzoid @raudi Чтобы быть справедливым, особенно если вы пишете код на долгий срок и для использования другими, уместно сделать что-то вроде того, что интерфейс Queue делает с remove против poll - иметь два версии метода, одна из которых возвращает null при (очень предсказуемом и распространенном) сбое, а другая выдает исключение, а затем пусть тот, кто его использует, сам решает, что использовать, в зависимости от того, что гарантирует более крупное приложение.

Snicksie
1 августа 2013 в 07:16
2

Думаю, if (text == null) return null; лучше, чем if (text != null) { ....} return null. Первый способ понять проще.

Kevin Meredith
5 декабря 2013 в 21:21
1

"null - отстой" - Дуг Ли code.google.com/p/guava-libraries/wiki/…

Gus
28 июня 2014 в 01:12
0

text.equalsIgnoreCase(b.text) может вызвать исключение нулевого указателя, если null передается в fromString(), тогда как b.text.equalsIgnoreCase(text) не будет (с учетом перечисленных экземпляров перечисления).

JoséMi
2 июля 2014 в 05:50
0

@Gus, пожалуйста, прочтите две строчки перед той, в которой говорится об ошибке: if (text != null) { ...

Gus
5 июля 2014 в 13:26
1

Извините, написал в fast ... Это не ошибка. Нулевой проверки можно избежать. Это похоже на "foo".equals(bar) вместо bar.equals("foo")

FearlessHyena
3 октября 2014 в 20:03
0

@ JoséMi Может также быть хорошей идеей переопределить значение по умолчанию toString () и заставить его возвращать "текст"

Paul
11 мая 2016 в 16:46
0

В добавлении поля text и методов getText() нет необходимости, поскольку в коде так же легко можно было бы использовать автоматически сгенерированный метод name(). Также возможно написать public static <E extends Enum<E>> com.mylibs.Enums.fromString(E enumType, String s), который будет работать для любого типа Enum.

chrisdowney
12 июля 2017 в 21:57
1

Альтернативой во многих случаях является наличие явного значения UNKNOWN для перечисления - таким образом вы можете избежать NPE и по-прежнему иметь возможность проверять неизвестные значения.

Dawood ibn Kareem
14 сентября 2017 в 20:03
4

Честно говоря, Джон Скит отвечал на вопрос, как это сделать, не генерируя и не перехватывая исключение. Тот факт, что он ответил на заданный вопрос, не означает, что он считает это хорошей идеей. @SanghyunLee

Martin Marconcini
10 апреля 2018 в 20:03
0

Чего стоит, Котлин… The valueOf() method throws an IllegalArgumentException if the specified name does not match any of the enum constants defined in the class.

avatar
Geoffrey Zheng
12 ноября 2009 в 15:52
129

Вот отличная утилита, которую я использую:

/**
 * 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 стирается.

whiskeysierra
31 июля 2010 в 10:14
188

Этот пустой блокиратор действительно сводит меня с ума, извините.

Martin Schröder
15 ноября 2011 в 17:09
33

@LazloBonin: исключения предназначены для исключительных условий, а не для потока управления. Получите себе копию Эффективная Java.

Nate C-K
30 ноября 2011 в 19:26
10

Если Java API, который вы хотите использовать, генерирует исключение, и вы не хотите, чтобы ваш код генерировал его, вы можете либо проглотить подобное исключение, либо переписать логику с нуля, чтобы исключение не генерировалось в первую очередь. Проглатывание исключения часто оказывается меньшим злом.

raudi
2 февраля 2012 в 07:52
47

Ужасный! Всегда всегда перехватывает исключения там, где их можно обработать. Пример выше - прекрасный пример , как НЕ делать этого . Почему? Таким образом, он возвращает NULL, и вызывающий затем должен проверить на NULL или выдать NPE. Если вызывающий знает, как справиться с ситуацией, то выполнение if vs. try-catch может выглядеть немного более элегантно, НО , если он не может справиться, он должен снова передать null, а вызывающий абонент снова должен проверять на NULL и т. Д. И т. Д.

Adrian M
6 февраля 2012 в 08:19
10

Чтобы быть справедливым по отношению к приведенному выше решению, действительно существуют случаи, когда вы должны возвращать null вместо того, чтобы бросать IllegalArgumentException и нарушать поток вашей программы, например, сопоставление перечислений между схемой веб-службы и схемой базы данных, где они не всегда являются одним целым -к одному. Однако я согласен с тем, что блок catch никогда не следует оставлять пустым. Поместите какой-нибудь код, например log.warn или что-то в этом роде, для отслеживания.

Manimaran Selvan
17 мая 2012 в 18:49
1

Абсолютно! Ведение исключения - это верное дело. Но я согласен с глотанием исключений.

Geoffrey Zheng
20 августа 2012 в 20:28
0

Теперь я бы просто использовал Guava Enums. Обратите внимание на различную обработку недопустимого ввода: getIfPresent возвращает Optional.absent(), что я бы предпочел использовать; тогда как valueOfFunction().apply() возвращает null.

YoYo
30 сентября 2012 в 05:18
1

Проблемы начинаются, когда вы хотите написать статический метод, который проверяет, соответствует ли строка экземпляру перечисления. Единственный способ проверить различные значения перечисления - это фактически вызвать функцию valueOf. Если бросает, результат ложный.

urig
12 февраля 2013 в 08:37
4

Я что-то пропустил? Какая дополнительная ценность вышеупомянутых методов по сравнению с простым использованием: MyEnum.valueOf(name)?

Brad Mace
15 мая 2014 в 19:49
2

@urig они нечувствительны к регистру, в отличие от valueOf

Stijn de Witt
26 июля 2015 в 13:29
2

Если вы собираетесь написать отдельную процедуру для сравнения без учета регистра, то почему бы на самом деле не выполнить проверку без учета регистра с использованием String.equalsIgnoreCase вместо этого жестко запрограммированного toUpperCase?

pjklauser
22 октября 2015 в 06:47
1

Эквивалентен методу getEnum apache-common's EnumUtils

nemetroid
29 июня 2017 в 08:51
1

@pjklauser Нет, метод getEnum в EnumUtils не выполняет поиск без учета регистра , а не .

Rob Stoecklein
9 января 2018 в 18:59
0

Мне нравится эта утилита. Мы добавили параметр «по умолчанию» на случай, если перечисление не может быть определено: final @Nullable T def

Darrell Teague
14 января 2019 в 15:44
1

Сейчас побочное обсуждение, но ... лучше возвращать Optional, если это то, что было задумано (например, разумно могло быть "unknown / undefined"). Затем NPE исчезает, но ошибка поиска не возвращает Exception как средство потока управления.

avatar
Peter Lawrey
9 мая 2009 в 17:23
36

Лучше всего использовать Blah.valueOf(string), но вы также можете использовать Enum.valueOf(Blah.class, string).

Murtaza Kanchwala
28 июня 2015 в 18:58
1

С учетом регистра, не помогает!

Peter Lawrey
29 июня 2015 в 10:18
0

@MurtazaKanchwala Не могли бы вы уточнить свой комментарий? Что ты пытаешься сделать?

Murtaza Kanchwala
29 июня 2015 в 17:45
2

Привет, @PeterLawrey, я пытался получить Enum из публичного перечисления String ObjectType {PERSON ("Person") public String parameterName; Тип объекта (String имя параметра) {this.parameterName = имя параметра; } общедоступная строка getParameterName () {return this.parameterName; } общедоступный статический ObjectType fromString (String parameterName) {if (parameterName! = null) {for (ObjectType objType: ObjectType.values ​​()) {if (parameterName.equalsIgnoreCase (objType.parameterName)) {return objType; }}} return null; }}

avatar
João Portela
9 мая 2009 в 16:33
77

Вы также должны быть осторожны со своим чемоданом. Позвольте мне объяснить: выполнение Blah.valueOf("A") работает, но Blah.valueOf("a") не работает. Тогда снова Blah.valueOf("a".toUpperCase(Locale.ENGLISH)) будет работать.

На Android следует использовать Locale.US, поскольку сулай указывает на.

tc.
28 ноября 2012 в 15:43
6

Остерегайтесь локали по умолчанию!

sulai
2 сентября 2013 в 17:44
4

Для пользователей Android, я хотел бы указать, что документация Android явно поощряет использование Locale.US для машиночитаемого ввода / вывода.

Stijn de Witt
26 июля 2015 в 13:34
2

@Trengot Да, к сожалению. Турция - хороший тому пример. Объедините это с неправильной обработкой кодировок по умолчанию в Java (в Windows по умолчанию используется Latin вместо Unicode), и вы обнаружите, что почти всегда небезопасно использовать версии методов по умолчанию, которые принимают кодировку или локаль. Вы должны почти всегда явно определять их.

Darrell Teague
29 мая 2018 в 20:45
0

Не уверен, что кодировки Java "по умолчанию" и другие "сломаны" сами по себе, но предоставлены, использование по умолчанию UTF-8 вместо переопределений (что всегда должно быть явным) сделало бы системы лучше для младших программистов, которые обычно не понимают концепции кодировки.