Сокращение для логики "If/Throw, Else/Return" в Java 8?
Есть ли более короткий синтаксис для if/throw else/return в Java 8? java.util.Optional
предоставляет средство для достижения этого в одном утверждении, но для этого требуется создать экземпляр Optional
с каждым вызовом, который имеет ненулевую ссылку.
Может ли это быть выполнено в одном выражении?
public static MyEnum fromString(String value) {
MyEnum result = enumMap.get(value);
if (result == null)
throw new IllegalArgumentException("Unsupported value: " + value);
return result;
}
Необязательный пример (плохо, требуется дополнительный экземпляр каждый раз)
public static MyEnum fromString(String value) {
return Optional.ofNullable(enumMap.get(value)).orElseThrow(
() -> new IllegalArgumentException("Unsupported value: " + value));
}
Ответы
Ответ 1
Влияние временного экземпляра Optional
незначительно. Обычно JVM будет определять свой временный характер и оптимизировать экземпляр. Даже если создание временного экземпляра не оптимизировано, воздействие одного временного объекта на управление памятью смехотворно низкое.
Однако, если карта изменчива, вы можете использовать следующий трюк:
public static MyEnum fromString(String value) {
return enumMap.computeIfAbsent(value, v -> {
throw new IllegalArgumentException("Unsupported value: " + v); });
}
Обратите внимание, что Map
не изменяется этим кодом, но все же должен быть изменен, поскольку неизменяемая карта может вызывать исключение UnsupportedOperation
для попытки использовать computeIfAbsent
, не проверяя, действительно ли операция действительно изменит карту.
Но в конце нет ничего плохого в Optional
. Но учтите, что код в вашем вопросе неверен. Выражение лямбда, которое вы передаете методу Optional.orElseThrow
, предназначено для предоставления желаемого исключения, а не для его броска:
public static MyEnum fromString(String value) {
return Optional.ofNullable(enumMap.get(value)).orElseThrow(() ->
new IllegalArgumentException("Unsupported value: " + value) // just return it
);
}
Ответ 2
Если вы готовы жить с NullPointerException
, вы можете сделать:
public static MyEnum fromString(String value) {
return requireNonNull(enumMap.get(value), () -> "Unsupported: " + value);
}
Это предполагает import static java.util.Objects.requireNonNull
Edit:
Если вы действительно относитесь к тому, какой тип исключения вы бросаете, просто используйте свой собственный статический метод утилиты:
static<T, X extends Throwable> T nonNullOrThrow(T val, Supplier<? extends X> exSupplier) throws X {
if (val != null) return val;
else throw exSupplier.get();
}
Затем вы сможете сделать
return nonNullOrThrow(enumMap.get(value), () -> new IllegalArgumentException("unsupported: " + k));