Это первый раз, когда я участвую в Gengwen Challenge.19День, подробности о событии уточняйте:Обновить вызов
Со временем капли воды и камни изнашиваются 😄
Что необязательно
Optional
даJAVA8
новая особенность .Optional
Класс находится вjava.util
Под пакетом это означает, что на самом деле это класс инструмента.
Давайте посмотрим, как официальное введениеOptional
из.
java.util.Optional
— это объект-контейнер, который может содержать или не содержать ненулевые значения, то есть он может содержать значения типа T или просто null. Если значение существует, тоisPresent()
метод вернет true, вызвав егоget()
Метод возвращает это значение.
Какая польза от опционального
Optional
Введение класса в основном предназначено для устранения исключения нулевого указателя (NullPointerException). В нашем обычном развитии, я полагаю, вы столкнулись с наиболееException
этоNullPointerException
. Вы можете быть простым, вы можете написать следующий код:
String cardNo = student.getCard().getCardNo().toUpperCase();
появляется в приведенном выше кодеNullPointerException
Слишком много нештатных ситуаций, если не хочешь показатьсяNullPointerException
Если это ненормально, то необходимо вывести пустое суждение следующим образом:
String cardNoUpper = null;
if(student != null){
Card card = student.getCard();
if(card != null){
String cardNo = card.getCardNo();
if (cardNo != null){
cardNoUpper = cardNo.toUpperCase();
}
}
}
Видно, что в каждый метод можно добавлять только ненулевые проверки, поэтому читабельность и ремонтопригодность кода относительно плохие. Чтобы упростить этот процесс, мы можем использоватьOptional
.Optional
Предоставляет множество полезных методов, поэтому нам не нужно выполнять явное обнаружение нулей.
Создайте два класса, давайте сначала научимсяOptional
как пользоваться и как пользоваться.
public class Student {
private String name;
private Integer age;
private Double grades;
// Card
private Card card;
//get set toString省略
}
public class Card {
private String cardNo;
private String cardName;
}
Создайте необязательный экземпляр
СоздайтеOptional
Есть три способа экземпляра, а именноof、empty、ofNullable
Три статических метода. Далее мы представим их отдельно.
-
Optional.of(T t)
: СоздаватьOptional
экземпляр t не должен быть нулевым;@Test public void test1(){ Optional<Student> student = Optional.of(new Student()); Student student1 = student.get(); System.out.println(student1); } 结果:Student{name='null', age=null, grades=null}
Если параметр метода of имеет значение null, возникает исключение нулевого указателя. Исключение возникает при создании
Optional
время экземпляра.Пример счетчика:
@Test
public void test1(){
Optional<Student> student2 = Optional.of(null);
}
-
Optional.empty()
: создать пустойOptional
Пример
Если вы просто хотите создать нульOptional
Например, вы можете использовать этот метод.
@Test
public void test2(){
Optional<Student> student = Optional.empty();
Student student1 = student.get();
System.out.println(student1);
}
ДолженNoSuchElementException
исключение происходит вget()
при вызове метода.
-
Optional.ofNullable(T t)
: t может быть нулевым. Если ненулевой, построить с переданным значениемOptional
; иначе вернуть пустое значениеOptional
.
@Test
public void test3(){
Optional<Student> student = Optional.ofNullable(new Student());
Student student1 = student.get();
System.out.println(student1);
}
结果:Student{name='null', age=null, grades=null}
еслиofNullable
Параметр передается в null, и результат такой же, какempty()
метод тот же. Исходный код выглядит следующим образом:
public static <T> Optional<T> ofNullable(T value) {
return value == null ? empty() : of(value);
}
научился создаватьOptional
Метод экземпляра, давайте рассмотрим другие методы далее.
Определите, содержит ли необязательный контейнер объект
-
boolean isPresent()·
: определяет, содержится ли значение, возвращает true, если значение существует, в противном случае возвращает false.
Пример:
@Test
public void test4(){
Optional<Student> student = Optional.ofNullable(new Student());
if(student.isPresent()){
Student student1 = student.get();
System.out.println(student1);
}
Optional<Student> student2 = Optional.ofNullable(null);
//取反
if (!student2.isPresent()) {
System.out.println("该对象为空值");
}
}
结果:
Student{name='null', age=null, grades=null}
该对象为空值
-
void ifPresent(Consumer<? super T> consumer)
: Буквальное отличие от вышеописанного метода. Если есть значение, выполнитьaccept.accept
; иначе ничего не делать.
public void ifPresent(Consumer<? super T> consumer) {
if (value != null)
consumer.accept(value);
}
Пример:
@Test
public void test5(){
Optional<Student> student = Optional.ofNullable(new Student("新三", 18, 55.0));
student.ifPresent((x)-> {
x.setName("李四");
});
System.out.println(student.get());
}
结果:Student{name='李四', age=18, grades=55.0}
Получить объект дополнительного контейнера
-
T get()
: Если вызывающий объект содержит значение, вернуть значение, в противном случае броситьNoSuchElementException
аномальный -
T orElse(T other)
: возвращает значение, если оно имеет значение, в противном случае возвращает указанный объект
Пример:
@Test
public void test6(){
Optional<Student> op = Optional.ofNullable(null);
// op 传入null,使用应返回我们指定的对象
Student st = op.orElse(new Student("新三", 18, 55.0));
System.out.println(st);
//传入Student
Optional<Student> op2 = Optional.ofNullable(new Student());
Student st2 = op2.orElse(new Student("新三", 18, 55.0));
System.out.println(st2);
}
Student{name='新三', age=18, grades=55.0}
Student{name='null', age=null, grades=null}
-
T orElseGet(Supplier<? extends T> other)
: вернуть его, если есть значение, в противном случае вернуть егоSupplier
Объекты, предоставляемые функциональными интерфейсами.
@Test
public void test7(){
Optional<Student> op = Optional.ofNullable(null);
Student st = op.orElseGet(()->{
//由于是一个函数式接口,里面可以写逻辑
Student student = new Student();
student.setAge(99);
student.setGrades(888.2);
student.setName("李四");
return student;
});
System.out.println(st);
}
结果:Student{name='李四', age=99, grades=888.2}k6a8
-
T orElseThrow(Supplier<? extends X> exceptionSupplier)
: верните его, если есть значение, в противном случае выбросьте егоSupplier
Исключения, предоставляемые функциональными интерфейсами
@Test
public void test8(){
Optional<Student> op = Optional.ofNullable(null);
Student st = op.orElseThrow(() -> new RuntimeException("值不存在"));
System.out.println(st);
}
-
<U> Optional<U> map(Function<? super T, ? extends U> mapper)
: выполняется на нем, если есть значениеmapper.apply
, и возвращает обработанныйOptional
. в противном случае вернутьсяOptional.empty()
. Исходный код выглядит следующим образом:
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));
}
}
Пример:
@Test
public void test9(){
Optional<Student> op = Optional.ofNullable(new Student("新,三", 18, 55.0));
Optional<String[]> s1 = op.map(s -> s.getName())
.map(s -> s.split(","));
System.out.println(Arrays.toString(s1.get()));
}
结果:[新, 三]
-
<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
:иmap
Аналогично, но требует, чтобы параметр былOptional
.
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));
}
}
Пример:
@Test
public void test10(){
Optional<Student> op = Optional.ofNullable(new Student("新,三", 18, 55.0));
Optional<String[]> s1 = op.flatMap(s -> Optional.ofNullable(s.getName())
.flatMap(s2 -> Optional.ofNullable(s2.split(",")))
);
System.out.println(Arrays.toString(s1.get()));
}
结果:[新, 三]
-
Optional<T> filter(Predicate<? super T> predicate)
: если значение существует и условие предиката выполнено, вернуть значение значенияOptional
, иначе возвратOptional.empty
public Optional<T> filter(Predicate<? super T> predicate) {
Objects.requireNonNull(predicate);
if (!isPresent())
return this;
else
return predicate.test(value) ? this : empty();
}
Пример:
@Test
public void test11(){
Optional<Student> optional = Optional.of(new Student("新三", 18, 55.0));
// 不符合断言条件 返回 Optional.empty
Optional<Student> opt = optional.filter(s -> {
return "张".equals(s.getName());
});
System.out.println(opt.orElse(new Student("李四", 22, 223.0)));
}
结果:Student{name='李四', age=22, grades=223.0}
здесьOptional
Предоставленные методы здесь почти закончены, следующим шагом является улучшение проблем, упомянутых в начале, как использоватьOptional
оптимизировать код?
String cardNoUpper = null;
if(student != null){
Card card = student.getCard();
if(card != null){
String cardNo = card.getCardNo();
if (cardNo != null){
cardNoUpper = cardNo.toUpperCase();
}
}
}
Сначала рефакторингStudent
в классеgetCard
метод, возвращающий егоOptional
Цитировать.
public class Student {
private String name;
private Integer age;
private Double grades;
private Card card;
// 其余省略。。。
public Optional<Card> getCard() {
return Optional.ofNullable(card);
}
public void setCard(Card card) {
this.card = card;
}
}
Подготовка завершена, приступаем к кодированию!
public static void main(String[] args) {
Student student = new Student("新三", 18, 55.0);
Card cardObj = new Card("ACafgtc", "工商银行");
student.setCard(cardObj);
//Optional<Student> o = Optional.ofNullable(null);
Optional<Student> o = Optional.ofNullable(student);
String cardNoUpper = o
.flatMap(s -> s.getCard()) // 获得 Optional<Card>
.map(card -> card.getCardNo()) // 获得 Card 内的 cardNo
.map(cardNo -> cardNo.toUpperCase())
.orElse("默认值");
System.out.println(cardNoUpper);
}
结果:ACAFGTC
можно и напрямуюStudent
Установите для него значение null, чтобы увидеть, произойдет ли исключение.
public static void main(String[] args) {
Optional<Student> o = Optional.ofNullable(null);
String cardNoUpper = o
.flatMap(s -> s.getCard()) // 获得 Optional<Card>
.map(card -> card.getCardNo()) // 获得 Card 内的 cardNo
.map(cardNo -> cardNo.toUpperCase())
.orElse("默认值");
System.out.println(cardNoUpper);
}
结果:默认值
Суммировать
заOptional
Некоторые люди считают, что нет необходимости изучать этот класс, потому что им кажется, что они не будут использовать его в своей работе. Идея на самом деле неверна, хотя мы не инкапсулируем возвращаемое значение нашего метода какOptional
, но учитсяOptional
Это еще очень нужно, чтобы не сказать лишнего, хотя бы понять и использовать. Поскольку сейчас многие библиотеки классов используютOptional
Инкапсулируйте возвращаемое значение, напримерSpring Data JPA, потоковый APIЖдать.
- Если у вас есть какие-либо вопросы по этой статье или есть ошибки в этой статье, пожалуйста, оставьте комментарий. Если вы считаете, что эта статья была вам полезна, ставьте лайк и подписывайтесь на нее.