1. preface

I believe that many of our partners have been java Of NPE(Null Pointer Exception) The so-called null pointer is very dizzy , Somebody said that “ prevent
NPE, It is the basic cultivation of programmers .” But self-cultivation is self-cultivation , It's also one of the biggest headaches for our programmers . before ,Google
Guava The project has been proposed to use Optional Class to wrap objects to solve NullPointerException. Affected by this ,JDK8 Also introduced in the Optional class , In the new edition of SpringData
Jpa and Spring Redis Data Support for this method has been implemented in . We're going to make the most of it today Java8 New features of
Optional To simplify the code as much as possible and to handle it efficiently NPE(Null Pointer Exception Null pointer exception )

 

2. First acquaintance Optional

First, let's look at the following code , It's going to be familiar
public static String getFirstName(User user) { if(null == user) { return
"Unkown"; } return student.getFirstName(); }
You can see from the above , It is to judge whether this instance is empty , Then let's look at the use java8 Of Optional Code after class
public static String getFirstName(User user) { return
Optional.ofNullable(user).map(u -> u.getFirstName()).orElse("Unkown"); }
In short ,Opitonal Class is Java To solve the problem that we usually judge whether the object is empty Can use null!=obj
Such a way of existence judgment , Which is a headache NPE(Null Pointer Exception
Null pointer exception ), meanwhile Optional Can make the code simpler , Higher readability , Code is more efficient to write .

below , Let's learn about magic efficiently Optional class !

 

3. Optional objects creating

First, let's open it Optional Inside of , Go and find out   First create a few Optional Object method extraction
public final class Optional<T> {
   private static final Optional<?> EMPTY = new Optional<>();
   private final T value;    // We can see that both construction squares are private  Private
   // explain   We can't go outside new come out Optional object    private Optional() {
        this.value = null;     }    private Optional(T value) {
        this.value = Objects.requireNonNull(value);     }
    // This static method is roughly   Is to create an object whose wrapper value is empty because there is no parameter assignment
   public static<T> Optional<T> empty() {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;         return t;     }
    // This static method is roughly   Is to create an object whose wrapper value is not empty   Because of the assignment
   public static <T> Optional<T> of(T value) {
        return new Optional<>(value);     }
    // This static method is roughly   If the parameter value Is empty , Create an empty object , If not empty , Then create a parameter object
   public static <T> Optional<T> ofNullable(T value) {
        return value == null ? empty() : of(value);     }  } Copy code
Do a simple example to show Corresponding to above
        // 1, Create a wrapper object with an empty value Optional object
        Optional<String> optEmpty = Optional.empty();
        // 2, Create a wrapper object with a non empty value Optional object
        Optional<String> optOf = Optional.of("optional");
        // 3, Create a wrapper object value that can be empty or not Optional object
        Optional<String> optOfNullable1 = Optional.ofNullable(null);
        Optional<String> optOfNullable2 = Optional.ofNullable("optional"); Copy code
We're about creating Optional The internal method of the object is roughly analyzed And then we will officially enter Optional Learning and using

 

4. Optional Use of class

 

    Serial number   
method
Method statement
1 private Optional()   Nonparametric structure , Construct an empty Optional
2 private Optional(T value)   According to the non null passed in value structure Optional
3 public static<T> Optional<T> empty() Returns an empty Optional, Of this instance value Is empty
4  public static <T> Optional<T> of(T value)
According to the non null passed in value structure Optional, And Optional(T value) The method has the same effect
5  public static <T> Optional<T> ofNullable(T value)
  And of(T value) The difference is that ,ofNullable(T value) Allows you to pass in an empty value,

When a null value is passed in, it creates an empty value Optional, When the value Non space time , And of() The effect is the same

6  public T get()   return Optional Value of , If the container is empty , Then throw out NoSuchElementException abnormal
7  public boolean isPresent()   Judge to be in charge Optional Is the value set
8  public void ifPresent(Consumer<? super T> consumer)
  Judge to be in charge Optional Is the value set , If there is a value , Call the Consumer Function interface
9  public Optional<T> filter(Predicate<? super T> predicate)
  If a value is set , And satisfied Predicate The judgment condition of , The Optional, Otherwise, an empty one is returned Optional
10  public<U> Optional<U> map(Function<? super T, ? extends U> mapper)
  If Optional Set value, Call the Function Processing values , That contains the processed value Optional, Otherwise, it returns null Optional

11  public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper)
  And map() Method type , The difference is it mapper The result is already one Optional, No more packaging of results is required
12  public T orElse(T other)   If Optional The value is not empty , The value is returned , Otherwise return other 
13 public T orElseGet(Supplier<? extends T> other)
If Optional The value is not empty , The value is returned , Otherwise, according to other Another one is generated
14 public <X extends Throwable> T orElseThrow(Supplier<? extends X>
exceptionSupplier) throws X If Optional The value is not empty , The value is returned , Otherwise, it passed supplier Throw an exception
 

4.1 Optional.get() method ( Returns the value of the object )

get() Method is to return a option Instance value of  , If value Return if not empty , If empty, an exception is thrown "No value present" , Source code :
    public T get() {         if (value == null) {
            throw new NoSuchElementException("No value present");         }
        return value;     }
example :
        User user=new User();         user.setFirstName("Tom");
        Optional.ofNullable(user).get();
 

4.2 Optional.isPresent() method ( Is the interpretation empty )

isPresent() Method is to return a boolean Type value , True if the object is not empty , If it is empty, then false , Source code :
 public boolean isPresent() {         return value != null;     }
example :
                User user=new User();         person.setFirstName("Tom");
        if (Optional.ofNullable(user).isPresent()){         // Write logic that cannot be empty
        System.out.println(" Not empty ");         }else{          // Write empty logic
         System.out.println(" Is empty ");         }
 

4 .3 Optional.ifPresent() method ( Determines whether it is empty and returns the function )

If the object is not empty , Then run the function body  , Source code :
  public void ifPresent(Consumer<? super T> consumer) {
        // If value Not empty , Then run accept Method body         if (value != null)
            consumer.accept(value);     }
example :
        User user = new User();         user.setFirstName("Tom");
        Optional.ofNullable(user).ifPresent(u -> System.out.println(" full name "+u.getFirstName()));
 

4.4 Optional.filter() method ( Filter objects )

filter() The general meaning of the method is , Accept an object , And then the conditional filter is applied , Return if the condition is met Optional Object itself , If not, null is returned Optional , Source code :
    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);         // If it is empty, it will be returned directly this
        if (!isPresent())             return this;         else
        // Determine whether the return itself is empty Optional
            return predicate.test(value) ? this : empty();     }
example :
        User user = new User();         user.setFirstName("Tom");
        Optional.ofNullable(user).filter(u -> u.getFirstName().equeal("Toms"));
 

4.5 Optional.map() method ( The object is repackaged )

map() Method will correspond to Funcation Objects in functional interfaces , Perform a second operation , Encapsulate it into a new object and return it to the Optional in  , Source code :
 public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);         // If it is empty, return to yourself
        if (!isPresent())             return empty();         else {
        // Otherwise, it returns the modified method Optional
            return Optional.ofNullable(mapper.apply(value));         }     }
example :
        User user = new User();         user.setFirstName("Tom");
        String optName = Optional.ofNullable(user).map(u -> u.getFirstName()).orElse("firstName Is empty ");
 

4.6 Optional.flatMap() method (Optional The object is repackaged )

map() Method will correspond to Optional< Funcation > Objects in functional interfaces , Perform a second operation , Encapsulate it into a new object and return it to the Optional in ,  Source code :
    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));         }     }
example :
        User user = new User();         user.setFirstName("Tom");
        Optional<Object> optName = Optional.ofNullable(user).map(u -> Optional.ofNullable(u.getFirstName()).orElse("firstName Is empty "));
 

4.7 Optional.orElse() method ( Null return object )

If the wrapper object is empty , On execution orElse In the method value, If not empty , The write object is returned  , Source code :
    public T orElse(T other) {     // If not empty , return value, If empty , return other
        return value != null ? value : other;     }
example :
        User user = new User();         user.setFirstName("Tom");
        Optional.ofNullable(user).orElse(new User("Tom"));
 

4.8 Optional.orElseGet() method ( Null return Supplier object )

This and orElse Very similar , The input parameters are different , The reference is Supplier object , Of the incoming object .get() method , If not null, the current object is returned  , Source code :
    public T orElseGet(Supplier<? extends T> other) {
        return value != null ? value : other.get();     }
example :
         Optional<Supplier<User>> sup=Optional.ofNullable(User::new);
        // call get() method , The constructor of the object is called , Get the real object
         Optional.ofNullable(user).orElseGet(sup.get());
Suppiler It's an interface , It's similar Spring Lazy loading of , After the declaration, it does not take up memory , Only execution get() After method , Will call the constructor to create the object
The syntax for creating objects is Supplier<User> supUser= User::new;  When needed supUser.get() that will do

 

4.9 Optional.orElseThrow() method ( Null returns an exception )

If empty , The defined exception is thrown , If not null, returns the current object ,  Source code :

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if (value != null) {             return value;         } else {
            throw exceptionSupplier.get();         }     }
example : This is the actual source code
        Member member = memberService.selectByPhone(request.getPhone());
        Optional.ofNullable(member).orElseThrow(() -> new ServiceException(" There is no query related data "));
 

4.10 The similarity methods were compared and analyzed

Maybe my partner saw this , If you don't use it, you will feel that orElse() and orElseGet() also orElseThrow() Very similar ,map() and flatMap() Good similarity
Hahaha, don't worry , It's all from this step , I would like to summarize the similarities and differences of different methods  orElse() and orElseGet() and orElseThrow() The similarities and differences of

The effect of the method is similar , If the object is not empty , The object is returned , If empty , The corresponding parameter in the method body is returned , Therefore, we can see that the parameters in the three method bodies are different orElse(T object )
orElseGet(Supplier < T > object ) orElseThrow( abnormal )

map() and orElseGet The similarities and differences of

The effect of the method is similar , The method parameters were re packaged , And return , Different parameters map(function function ) flatmap(Optional< function > function )

How to use it , It should be defined according to the business scenario and code specification , Now I can take a simple look at how I use magic in actual combat Optional

 

5. Optional Precautions for use

Optional It's really easy to use , It can be completely replaced if Judging ?  I think it must be after you use it Optional Ideas that may arise after that , The answer is No
  Take the simplest chestnut : example 1: What if I just want to judge whether a variable of an object is empty and make a judgment ?
User user = new User(); user.setFirstName(""); // Common judgment
if(StringUtils.isNotBlank(user.getFirstName())){   // Execution code block with name not empty }
// use Optional Judge
Optional.ofNullable(user).map(u -> u.getFirstName()).orElse("firstName Is empty ");
I think this example can well illustrate this problem ,
It's just a simple judgment , If you use it Optional We also need to consider the packaging value , Consider code writing , Consider method calls , Although there is only one line , But the readability is not good , If other programmers read it , I don't think so if It's obvious

 

6. jdk1.9 Yes Optional optimization

First, three methods are added : or(),ifPresentOrElse() and stream(). 

 

6.1 ifPresentOrElse(Consumer,Runnable)

ifPresentOrElse()  Method has two parameters : One Consumer And a Runnable. If the object is not empty , Will execute Consumer
The action of , Otherwise run Runnable. comparison ifPresent() More OrElse judge .

ifPresentOrElse(Consumer,Runnable) Can be interpreted as :ifPresent Just Consumer,OrElse Just Runnable. This is Java
9 The only way to enhance it .

example :Stream Flow filtration 3 Multiple of , And then through the findFirst Find the first one 3 Multiple of . If you find a value like this , Just print The console is printed out ; If you don't find a value like this , Just output " Can't find 3 Multiple of "
IntStream.of(1, 2, 4) .filter(i -> i % 3 == 0) .findFirst()
.ifPresentOrElse(System.out::println, () -> { System.out.println(" Can't find 3 Multiple of ");
});
 

6.2 Optional.or(Supplier)

or()  And orElse The method is similar , If the object is not empty, the object is returned , Return if empty or() Method .

example : Filter array ['a', 'b',
'c'],isDigit Determine whether there are numeric characters in the array , Obviously not , therefore findFirst No such value was found . So a default value is generated : Optional.of('0')
char digit = Stream.of('a', 'b', 'c') .filter(e -> Character.isDigit(e))
.findFirst() .or(() -> Optional.of('0')).get(); System.out.println(digit); //0
 

6.3 Optional.stream()

**stream()** take Optional convert to stream, That contains the value, if any stream, If it's not worth it , Just return empty stream.

example : In this case Optional.stream() Method returns an object that contains only one maximum element Stream flow .
OptionalInt opt1 = IntStream.of(2, 5, 6).max(); // Maximum value OptionalInt opt2 =
IntStream.of(1, 3, 7).max(); // Maximum value IntStream.concat(opt1.stream(),
opt2.stream()) // take 2 Stream merging .forEach(System.out::println); // Print the merged stream data 6,7
 

 

Technology