Как получить значение enum из строки в Java?
Решение: метод valueOf() и обработка исключений
Самый простой и встроенный способ получить значение enum из строки — использовать метод valueOf(String), который автоматически генерируется для каждого enum в Java. Однако этот метод чувствителен к регистру и выбрасывает IllegalArgumentException, если строка не соответствует ни одной константе.
public enum OrderStatus {
NEW,
PROCESSING,
SHIPPED,
DELIVERED,
CANCELLED
}
// Использование
String input = "PROCESSING";
OrderStatus status = OrderStatus.valueOf(input); // Работает
String badInput = "processing"; // Нижний регистр
OrderStatus status2 = OrderStatus.valueOf(badInput); // Выбросит IllegalArgumentException
Безопасный способ с обработкой регистра
Чтобы сделать код устойчивым к разному регистру, можно преобразовать входную строку к верхнему регистру перед вызовом valueOf():
public static OrderStatus fromString(String input) {
if (input == null) {
throw new IllegalArgumentException("Строка не может быть null");
}
return OrderStatus.valueOf(input.toUpperCase());
}
Добавление собственного поля и метода
Если вам нужно сопоставлять строки, которые отличаются от имён констант (например, с пробелами или другими значениями), лучше добавить в enum поле и метод для поиска:
public enum OrderStatus {
NEW("новый"),
PROCESSING("в обработке"),
SHIPPED("отправлен"),
DELIVERED("доставлен"),
CANCELLED("отменён");
private final String displayName;
OrderStatus(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
// Поиск по displayName (регистронезависимый)
public static OrderStatus fromDisplayName(String displayName) {
for (OrderStatus status : OrderStatus.values()) {
if (status.displayName.equalsIgnoreCase(displayName)) {
return status;
}
}
throw new IllegalArgumentException("Неизвестный статус: " + displayName);
}
// Поиск по имени константы (регистронезависимый)
public static OrderStatus fromName(String name) {
for (OrderStatus status : OrderStatus.values()) {
if (status.name().equalsIgnoreCase(name)) {
return status;
}
}
throw new IllegalArgumentException("Неизвестное имя: " + name);
}
}
Использование Optional для безопасного поиска
С Java 8 можно использовать Optional, чтобы избежать исключений и вернуть пустое значение, если строка не найдена:
import java.util.Optional;
public static Optional<OrderStatus> findStatus(String input) {
if (input == null) return Optional.empty();
for (OrderStatus status : OrderStatus.values()) {
if (status.name().equalsIgnoreCase(input.trim())) {
return Optional.of(status);
}
}
return Optional.empty();
}
// Использование
String userInput = " shipped ";
Optional<OrderStatus> statusOpt = findStatus(userInput);
statusOpt.ifPresent(s -> System.out.println("Найден статус: " + s));
Рекомендации
- Всегда проверяйте входную строку на null и пустые значения
- Используйте
trim()для удаления лишних пробелов - Для критичных к производительности мест (например, обработка тысяч запросов) можно создать статический HashMap для быстрого поиска
- Рассмотрите использование
Enum.valueOf()только если вы полностью контролируете входные данные
Выберите подход, который лучше всего подходит для вашей задачи. Для простых случаев достаточно valueOf() с преобразованием регистра, для более сложных сопоставлений — добавляйте кастомные поля и методы поиска.
Альтернативный подход: использование HashMap для быстрого поиска
Если ваш enum содержит много констант и вам нужна максимальная производительность при частых запросах, используйте статический HashMap. Этот подход особенно полезен, когда строки-ключи отличаются от имён констант.
import java.util.HashMap;
import java.util.Map;
public enum HttpStatus {
OK(200, "OK"),
NOT_FOUND(404, "Not Found"),
INTERNAL_SERVER_ERROR(500, "Internal Server Error");
private final int code;
private final String description;
private static final Map<String, HttpStatus> LOOKUP_MAP = new HashMap<>();
static {
for (HttpStatus status : HttpStatus.values()) {
// Ключ — код или описание в нижнем регистре
LOOKUP_MAP.put(String.valueOf(status.code), status);
LOOKUP_MAP.put(status.description.toLowerCase(), status);
}
}
HttpStatus(int code, String description) {
this.code = code;
this.description = description;
}
public static HttpStatus fromString(String key) {
if (key == null) return null;
return LOOKUP_MAP.get(key.trim().toLowerCase());
}
}
Преимущества: поиск за O(1), легко добавлять новые сопоставления.
Недостатки: требует больше памяти, нужно обновлять map при изменении enum.
Этот метод идеален для enum с фиксированным набором констант и частыми запросами, например, в парсерах или конфигурационных файлах.