Java Language
Необязательный
Поиск…
Вступление
Optional
- это контейнерный объект, который может содержать или не содержать ненулевое значение. Если значение присутствует, isPresent()
вернет true
и get()
вернет значение.
orElse()
дополнительные методы, которые зависят от наличия содержащегося значения, например orElse()
, который возвращает значение по умолчанию, если значение отсутствует, и ifPresent()
который выполняет блок кода, если это значение присутствует.
Синтаксис
- Необязательный.путь () // Создает пустой Необязательный экземпляр.
- Необязательно. (Значение) // Возвращает необязательный параметр с указанным ненулевым значением. Исключение NullPointerException будет выбрано, если переданное значение равно null.
- Необязательный.ofNullable (значение) // Возвращает необязательный параметр с указанным значением, которое может быть нулевым.
Возврат значения по умолчанию, если Необязательный пуст
Не используйте параметр Optional.get()
поскольку это может NoSuchElementException
. Способы Optional.orElse(T)
и Optional.orElseGet(Supplier<? extends T>)
обеспечивают способ предоставления значения по умолчанию в случае, если Опция пуста.
String value = "something";
return Optional.ofNullable(value).orElse("defaultValue");
// returns "something"
return Optional.ofNullable(value).orElseGet(() -> getDefaultValue());
// returns "something" (never calls the getDefaultValue() method)
String value = null;
return Optional.ofNullable(value).orElse("defaultValue");
// returns "defaultValue"
return Optional.ofNullable(value).orElseGet(() -> getDefaultValue());
// calls getDefaultValue() and returns its results
orElse
различие между orElse
и orElseGet
заключается в том, что последнее оценивается только тогда, когда параметр Необязательный пуст, в то время как аргумент, предоставленный первому, оценивается, даже если опция не является пустой. Поэтому orElse
следует использовать только для констант и никогда не предоставлять значение, основанное на каких-либо вычислениях.
карта
Используйте метод map()
для параметра « Optional
для работы со значениями, которые могут быть null
без явных проверок null
:
(Обратите внимание, что операции map()
и filter()
вычисляются сразу же, в отличие от их экземпляров Stream, которые оцениваются только при операции терминала .)
Синтаксис:
public <U> Optional<U> map(Function<? super T,? extends U> mapper)
Примеры кода:
String value = null;
return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "NONE"
String value = "something";
return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "SOMETHING"
Поскольку Option.map () возвращает пустую опцию, когда ее функция отображения возвращает значение null, вы можете связать несколько операций map () как форму нуль-безопасного разыменования. Это также известно как надежная цепочка .
Рассмотрим следующий пример:
String value = foo.getBar().getBaz().toString();
Любой из getBar
, getBaz
и toString
потенциально может генерировать getBaz
NullPointerException
.
Вот альтернативный способ получить значение toString()
используя Optional
:
String value = Optional.ofNullable(foo)
.map(Foo::getBar)
.map(Bar::getBaz)
.map(Baz::toString)
.orElse("");
Это вернет пустую строку, если какая-либо из функций отображения вернет null.
Ниже приведен еще один пример, но немного другой. Он напечатает значение только в том случае, если ни одна из функций сопоставления не вернула значение null.
Optional.ofNullable(foo)
.map(Foo::getBar)
.map(Bar::getBaz)
.map(Baz::toString)
.ifPresent(System.out::println);
Выбросьте исключение, если нет значения
Используйте метод orElseThrow()
Optional
чтобы получить содержащееся значение или выбросить исключение, если оно не было установлено. Это похоже на вызов get()
, за исключением того, что он допускает произвольные типы исключений. Метод берет поставщика, который должен вернуть исключение, которое нужно выбросить.
В первом примере метод просто возвращает содержащееся значение:
Optional optional = Optional.of("something");
return optional.orElseThrow(IllegalArgumentException::new);
// returns "something" string
Во втором примере метод генерирует исключение, потому что значение не задано:
Optional optional = Optional.empty();
return optional.orElseThrow(IllegalArgumentException::new);
// throws IllegalArgumentException
Вы также можете использовать синтаксис лямбда, если требуется выброс исключения с сообщением:
optional.orElseThrow(() -> new IllegalArgumentException("Illegal"));
Фильтр
filter()
используется, чтобы указать, что вы хотите получить значение только в том случае, если оно соответствует вашему предикату.
Подумайте об этом, как if (!somePredicate(x)) { x = null; }
.
Примеры кода:
String value = null;
Optional.ofNullable(value) // nothing
.filter(x -> x.equals("cool string"))// this is never run since value is null
.isPresent(); // false
String value = "cool string";
Optional.ofNullable(value) // something
.filter(x -> x.equals("cool string"))// this is run and passes
.isPresent(); // true
String value = "hot string";
Optional.ofNullable(value) // something
.filter(x -> x.equals("cool string"))// this is run and fails
.isPresent(); // false
Использование дополнительных контейнеров для примитивных типов номеров
OptionalDouble
, OptionalInt
и OptionalLong
работают как Optional
, но специально предназначены для переноса примитивных типов:
OptionalInt presentInt = OptionalInt.of(value);
OptionalInt absentInt = OptionalInt.empty();
Поскольку числовые типы имеют значение, для null нет специальной обработки. Пустые контейнеры можно проверить с помощью:
presentInt.isPresent(); // Is true.
absentInt.isPresent(); // Is false.
Точно так же существуют сокращения для управления стоимостью:
// Prints the value since it is provided on creation.
presentInt.ifPresent(System.out::println);
// Gives the other value as the original Optional is empty.
int finalValue = absentInt.orElseGet(this::otherValue);
// Will throw a NoSuchElementException.
int nonexistentValue = absentInt.getAsInt();
Выполнить код, только если имеется значение
Optional<String> optionalWithValue = Optional.of("foo");
optionalWithValue.ifPresent(System.out::println);//Prints "foo".
Optional<String> emptyOptional = Optional.empty();
emptyOptional.ifPresent(System.out::println);//Does nothing.
Ленько предоставлять значение по умолчанию с помощью поставщика
Нормальный orElse
метод принимает Object
, так что вы могли бы задаться вопросом, почему есть возможность предоставить Supplier
здесь ( orElseGet
метод).
Рассматривать:
String value = "something";
return Optional.ofNullable(value)
.orElse(getValueThatIsHardToCalculate()); // returns "something"
Он все равно вызовет getValueThatIsHardToCalculate()
хотя результат не используется, поскольку необязательный не пуст.
Чтобы избежать этого наказания, вы предоставляете поставщика:
String value = "something";
return Optional.ofNullable(value)
.orElseGet(() -> getValueThatIsHardToCalculate()); // returns "something"
Таким образом getValueThatIsHardToCalculate()
будет вызываться только в том случае, если параметр Optional
пуст.
FlatMap
flatMap
похож на map
. Разница описывается javadoc следующим образом:
Этот метод похож на
map(Function)
, но предоставленный сопоставитель - это тот, результат которого уже являетсяOptional
, и если вызывается,flatMap
не обертывает его дополнительнымOptional
.
Другими словами, когда вы связываете вызов метода, который возвращает Optional
, использование Optional.flatMap
позволяет избежать создания вложенных Optionals
.
Например, учитывая следующие классы:
public class Foo {
Optional<Bar> getBar(){
return Optional.of(new Bar());
}
}
public class Bar {
}
Если вы используете Optional.map
, вы получите вложенный Optional
; т.е. Optional<Optional<Bar>>
.
Optional<Optional<Bar>> nestedOptionalBar =
Optional.of(new Foo())
.map(Foo::getBar);
Однако, если вы используете Optional.flatMap
, вы получите простой Optional
; т.е. Optional<Bar>
.
Optional<Bar> optionalBar =
Optional.of(new Foo())
.flatMap(Foo::getBar);