1. Использование необязательного введения
1.1, проблемы с кодом ведут
Обычно встречается при написании программNullPointerException
, поэтому программа часто считается непустой:
User user = getUserById(id);
if (user != null) {
String username = user.getUsername();
System.out.println("Username is: " + username); // 使用 username
}
Чтобы решить эту неловкую ситуацию, JDK, наконец, присоединился к Java8.Optional
класс, видOptional
Javadoc описывает:
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
Это список, который может содержать или не содержатьnull
контейнер для ценностей. если значение существует, тоisPresent()
метод вернетtrue
,перечислитьget()
Метод возвращает объект.
1.2. Расширенное решение
мы предполагаем, чтоgetUserById
Это уже объективно существующий метод, который нельзя изменить, тогда используйтеisPresent
иget
Два метода, теперь мы можем написать следующий код:
Optional<User> user = Optional.ofNullable(getUserById(id));
if (user.isPresent()) {
String username = user.get().getUsername();
System.out.println("Username is: " + username); // 使用 username
}
Вроде бы код красивый, а по сути это то же самое, что и предыдущее суждениеnull
Принципиальной разницы в коде значения нет, но используйтеOptional
инкапсулироватьvalue, увеличивая количество кода. Итак, давайте посмотримOptional
Какие еще методы предусмотрены, чтобы мы могли использовать их лучше (с правильной осанкой)Optional
.
Два, опционально три статических метода построения
1 Обзор:
JDK предоставляет три статических метода для созданияOptional
:
-
Optional.of(T value)
public static <T> Optional<T> of(T value) { return new Optional<>(value); }
Этот метод использует не-
null
изvalueпостроитьOptional
,возвращениеOptional
содержитvalueэто значение. Для этого метода входящий параметр не должен бытьnull
, иначе выкинетNullPointerException
. -
Optional.ofNullable(T value)
public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
этот метод и
of
Отличие методов в том, что входящие параметры могут бытьnull
- Но предыдущий javadoc не говоритOptional
может содержать только не-null
Стоит ли оно того? мы можем видетьofNullable
Исходный код метода.Получается, что этот метод будет определять, является ли входящий параметр
null
, еслиnull
, возвратOptional.empty()
. -
Optional.empty()
public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; }
Этот метод используется для построения пустого
Optional
, этоOptional
не содержит значения - на самом деле базовая реализация по-прежнемуЕсли значение в необязательном параметре равно нулю, то необязательный элемент находится в состоянии, которое не содержит значения., а затем на уровне APIOptional
исполнение не может содержатьnull
значение так, чтобыOptional
существует толькосодержит значениеине содержит значениядва состояния.
2) Анализ:
Ранее в javadoc также упоминалось,Optional
изisPresent()
Метод используется для определения того, содержит ли он значение,get()
получитьOptional
содержит значения—Стоит отметить, что если значение не существует, то есть при вызове метода get() для Optional.empty будет выброшено исключение NoSuchElementException..
3) Резюме:
1) Необязательный.of(obj): требуется, чтобы входящий объект не мог иметь значение null, иначе перед входом в роль он попадет в NullPointerException. 2) Необязательный.ofNullable(obj): он конструирует необязательный экземпляр интеллектуальным и прощающим способом.Если он не отклонен, передайте null, чтобы получить Optional.empty(), если он не нулевой, вызовите Optional.of(obj) . Означает ли это, что нам нужно использовать Optional.ofNullable(obj) только один раз и навсегда, чтобы сконструировать экземпляр Optional таким образом, который не изменится и должен быть изменен? должны быть выставлены вот так, и это личное.
3. Подробное объяснение общих методов опционального
3.1. Обзор распространенных методов Факультативного
-
Optional.of(T t)
Возвращает указанное значение, инкапсулированное в необязательный элемент, или создает исключение NullPointerException, если значение равно null.
-
Optional.empty()
Создает пустой необязательный экземпляр.
-
Optional.ofNullable(T t)
Возвращает указанное значение после его инкапсуляции с необязательным.Если значение равно null, возвращается пустой необязательный объект.
-
isPresent
Возвращает true, если значение существует, иначе возвращает false
-
ifPresent
Если необязательный экземпляр имеет значение, вызовите для него потребителя, в противном случае ничего не делайте. Чтобы понять метод ifPresent, вам сначала нужно понять класс Consumer. Короче говоря, класс Consumer содержит абстрактный метод. Этот абстрактный метод работает с входящим значением, но не возвращает значение. Java8 поддерживает передачу параметров напрямую через лямбда-выражения без использования интерфейсов. Если экземпляр Optional имеет значение, вызов ifPresent() может принять сегмент интерфейса или лямбда-выражение.
-
Optional.get()
Если значение существует, верните значение, завернутое в необязательный элемент, в противном случае создайте исключение NoSuchElementException.
-
orElse(T t)
Если вызывающий объект содержит значение, вернуть это значение, в противном случае вернуть t.
-
orElseGet(Supplier s)
Если вызывающий объект содержит значение, вернуть это значение, в противном случае вернуть значение, полученное с помощью s.
-
orElseThrow()
Он выдаст исключение, когда объект пуст.
-
map(Function f)
Если значение существует, выполните предоставленный вызов функции сопоставления для этого значения.
-
flatMap(Function mapper)
Выполняет предоставленный вызов функции сопоставления для значения, если оно существует, возвращая значение типа Optional , в противном случае возвращает пустой объект Optional.
3.2. Подробное объяснение общих методов опционального
3.2.1, если присутствует
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
еслиOptional
Если есть значение, вызовите это значениеconsumer.accept
, иначе ничего не делать.
Итак, для примера во введении мы можем изменить его на:
Optional<User> user = Optional.ofNullable(getUserById(id));
user.ifPresent(u -> System.out.println("Username is: " + u.getUsername()));
3.2.2 илиЕще
public T orElse(T other) {
return value != null ? value : other;
}
еслиOptional
Если есть значение, верните его, иначе вернитеorElse
Параметры, переданные в метод.
User user = Optional
.ofNullable(getUserById(id))
.orElse(new User(0, "Unknown"));
System.out.println("Username is: " + user.getUsername());
3.2.3 или ElseGet
public T orElseGet(Supplier<? extends T> other) {
return value != null ? value : other.get();
}
orElseGet
иorElse
Отличие метода в том, чтоorElseGet
В метод передается параметрSupplier
Реализация интерфейса - когдаOptional
Когда есть значение, вернуть значение; когдаOptional
Когда нет никакой ценности вSupplier
полученное значение.
User user = Optional
.ofNullable(getUserById(id))
.orElseGet(() -> new User(0, "Unknown"));
System.out.println("Username is: " + user.getUsername());
3.2.4 или ElseThrow
public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
if (value != null) {
return value;
} else {
throw exceptionSupplier.get();
}
}
orElseThrow
иorElse
Отличие метода в том, чтоorElseThrow
метод, когдаOptional
Когда есть значение, возвращается значение; когда нет значения, будет выброшено исключение, и выброшенное исключение будет передано вexceptionSupplierпоставка.
Например:
В контроллере SpringMVC мы можем настроить единую обработку различных исключений. При запросе сущности, если есть соответствующая запись в БД, возвращается запись, иначе может быть выкинутEntityNotFoundException
,иметь дело сEntityNotFoundException
В методе мы возвращаем клиенту информацию, соответствующую Http-коду состояния 404 и исключению —orElseThrow
Идеально подходит для этого сценария.
@RequestMapping("/{id}")
public User getUser(@PathVariable Integer id) {
Optional<User> user = userService.getUserById(id);
return user.orElseThrow(() -> new EntityNotFoundException("id 为 " + id + " 的用户不存在"));
}
@ExceptionHandler(EntityNotFoundException.class)
public ResponseEntity<String> handleException(EntityNotFoundException ex) {
return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
}
3.2.5, карта
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value));
}
}
если текущийOptional
заOptional.empty
, все равно возвращаетсяOptional.empty
; иначе вернуть новыйOptional
,ДолженOptional
Содержит: функцииmapperвvalueВыходное значение при использовании в качестве входного.
String username = Optional.ofNullable(getUserById(id))
.map(user -> user.getUsername())
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
и мы можем использовать его несколько разmap
работать:
Optional<String> username = Optional.ofNullable(getUserById(id))
.map(user -> user.getUsername())
.map(name -> name.toLowerCase())
.map(name -> name.replace('_', ' '))
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
3.2.6, плоская карта
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value));
}
}
flatMap
метод сmap
Отличие метода в том, чтоmap
функция в параметре методаmapper
Результатом является значение, затемmap
метод будет использоватьOptional.ofNullable
оберните это какOptional
;иflatMap
функция, которая требует аргументовmapper
выходOptional
.
Optional<String> username = Optional.ofNullable(getUserById(id))
.flatMap(user -> Optional.of(user.getUsername()))
.flatMap(name -> Optional.of(name.toLowerCase()))
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
3.2.7, фильтр
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
filter
метод принимаетPredicate
иди прямоOptional
Значение, содержащееся в фильтре, фильтруется, и если содержащееся значение удовлетворяет условию, оно все равно возвращается.Optional
; иначе возвратOptional.empty
.
Optional<String> username = Optional.ofNullable(getUserById(id))
.filter(user -> user.getId() < 10)
.map(user -> user.getUsername());
.orElse("Unknown")
.ifPresent(name -> System.out.println("Username is: " + name));
4. Пример использования Необязательно
4.1. Используйте дисплей 1
Когда user.isPresent() имеет значение true, он получает набор сопоставлений связанных с ним заказов, а если значение false, он возвращает пустой набор. map, мы можем сделать это одной строкой:
return user.map(u -> u.getOrders()).orElse(Collections.emptyList())
//上面避免了我们类似 Java 8 之前的做法
if(user.isPresent()) {
return user.get().getOrders();
} else {
return Collections.emptyList();
}
Карты можно каскадировать бесконечно, например, чтобы получить прописную форму имени пользователя, пройдя на один уровень глубже:
return user.map(u -> u.getUsername())
.map(name -> name.toUpperCase())
.orElse(null);
Предыдущая практика:
User user = .....
if(user != null) {
String name = user.getUsername();
if(name != null) {
return name.toUpperCase();
} else {
return null;
}
} else {
return null;
}
filter() : если есть значение и условие выполнено, вернуть необязательный элемент, содержащий значение, в противном случае вернуть пустой необязательный элемент.
Optional<String> longName = name.filter((value) -> value.length() > 6);
System.out.println(longName.orElse("The name is less than 6 characters"));