1. Введение
В некоторых случаях мы можем захотеть вернуться к другому опциональному
экземпляру, если другой пуст.
В этом уроке мы кратко упомянем, как мы можем это сделать — что сложнее, чем кажется.
Для ознакомления с необязательным классом Java взгляните на нашу предыдущую статью .
2. Ява 8
В Java 8 нет прямого способа вернуть другой необязательный
параметр, если первый пуст.
Поэтому мы можем реализовать собственный пользовательский метод:
public static <T> Optional<T> or(Optional<T> optional, Optional<T> fallback) {
return optional.isPresent() ? optional : fallback;
}
А на практике:
@Test
public void givenOptional_whenValue_thenOptionalGeneralMethod() {
String name = "Filan Fisteku";
String missingOptional = "Name not provided";
Optional<String> optionalString = Optional.ofNullable(name);
Optional<String> fallbackOptionalString = Optional.ofNullable(missingOptional);
assertEquals(
optionalString,
Optionals.or(optionalString, fallbackOptionalString));
}
@Test
public void givenEmptyOptional_whenValue_thenOptionalGeneralMethod() {
Optional<String> optionalString = Optional.empty();
Optional<String> fallbackOptionalString = Optional.ofNullable("Name not provided");
assertEquals(
fallbackOptionalString,
Optionals.or(optionalString, fallbackOptionalString));
}
2.1. Ленивая оценка
Вышеупомянутое решение имеет один серьезный недостаток — нам нужно оценить обе необязательные
переменные, прежде чем использовать наш собственный метод or()
.
Представьте, что у нас есть два метода, возвращающие необязательные
s, оба запрашивают базу данных под капотом. Было бы неприемлемо, с точки зрения производительности, вызывать их оба, если уже первый метод возвращает нужное нам значение.
Создадим простой класс ItemsProvider
:
public class ItemsProvider {
public Optional<String> getNail(){
System.out.println("Returning a nail");
return Optional.of("nail");
}
public Optional<String> getHammer(){
System.out.println("Returning a hammer");
return Optional.of("hammer");
}
}
Вот как мы можем связать эти методы и воспользоваться преимуществами ленивых вычислений :
@Test
public void givenTwoOptionalMethods_whenFirstNonEmpty_thenSecondNotEvaluated() {
ItemsProvider itemsProvider = new ItemsProvider();
Optional<String> item = itemsProvider.getNail()
.map(Optional::of)
.orElseGet(itemsProvider::getHammer);
assertEquals(Optional.of("nail"), item);
}
Приведенный выше тестовый пример печатает только «Возврат гвоздя»
. Это ясно указывает на то, что был выполнен только метод getNail()
.
3. Ява 9
В Java 9 добавлен метод or()
, который мы можем использовать для получения Optional
или другого значения, если этого Optional
нет .
Давайте посмотрим это на практике на быстром примере:
public static Optional<String> getName(Optional<String> name) {
return name.or(() -> getCustomMessage());
}
Мы использовали вспомогательный метод, чтобы помочь нам с нашим примером:
private static Optional<String> getCustomMessage() {
return Optional.of("Name not provided");
}
Мы можем протестировать его и понять, как он работает. Следующий тестовый пример демонстрирует случай, когда необязательный
параметр имеет значение:
@Test
public void givenOptional_whenValue_thenOptional() {
String name = "Filan Fisteku";
Optional<String> optionalString = Optional.ofNullable(name);
assertEquals(optionalString, Optionals.getName(optionalString));
}
4. Использование гуавы
Другой способ сделать это — использовать метод or() класса
Optional
класса guava. Во-первых, нам нужно добавить гуаву
в наш проект (последнюю версию можно найти здесь ):
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.0.1-jre</version>
</dependency>
Теперь мы можем продолжить тот же пример, что и ранее:
public static com.google.common.base.Optional<String>
getOptionalGuavaName(com.google.common.base.Optional<String> name) {
return name.or(getCustomMessageGuava());
}
private static com.google.common.base.Optional<String> getCustomMessageGuava() {
return com.google.common.base.Optional.of("Name not provided");
}
Как мы видим, он очень похож на показанный выше. Однако он имеет небольшое отличие в названии метода и точно такой же, как метод or()
класса Optional
из JDK 9.
Теперь мы можем протестировать его, как в примере выше:
@Test
public void givenGuavaOptional_whenInvoke_thenOptional() {
String name = "Filan Fisteku";
Optional<String> stringOptional = Optional.of(name);
assertEquals(name, Optionals.getOptionalGuavaName(stringOptional));
}
@Test
public void givenGuavaOptional_whenNull_thenDefaultText() {
assertEquals(
com.google.common.base.Optional.of("Name not provided"),
Optionals.getOptionalGuavaName(com.google.common.base.Optional.fromNullable(null)));
}
5. Вывод
Это была краткая статья, иллюстрирующая, как добиться функциональности «Необязательный» или «Еще необязательный»
.
Код для всех описанных здесь примеров и многое другое можно найти на GitHub .