It’s Optional

1. Introduction

Java (NPE) Null Pointer Exception (NPE) Null Pointer Exception (NPE) We are going to use the new Java8 feature Optional to simplify code as much as possible and efficiently handle NPE (Null Pointer Exception)

2. Meet Optional and use it

In simple terms, Opitonal class is provided by Java in order to solve the problem of determining whether an object is empty will use null! =obj (Null Pointer Exception) = obJ (Null Pointer Exception) = OBJ (Null Pointer Exception)

General judgment:/ / object
        // Attributes are name, age
        Person person=new Person();
       if (null==person){
            return "The person is null";
        }
        return person;
Copy the code
Optional:/ / object
        // Attributes are name, age
        Person person=new Person();
        return Optional.ofNullable(person).orElse("The person is null");
Copy the code

The test shows the Class Person code (take a look at this if you don’t understand) :


public class Person {
    private String name;
    private Integer age;

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public Person(a) {}public String getName(a) {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge(a) {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age; }}Copy the code

Below, we will learn about the magical Optional class efficiently!

2.1 Optional object Creation

So let’s go inside Optional and take a look at some of the ways that we can create Optional objects

public final class Optional<T> {
   private static finalOptional<? > EMPTY =new Optional<>();
   private final T value;
   // We can see that both construction squares are private
   // We can't create Optional objects outside
   private Optional(a) {
        this.value = null;
    }
   private Optional(T value) {
        this.value = Objects.requireNonNull(value);
    }
    // This static method basically creates an object whose wrapper value is empty because there are no arguments assigned
   public static<T> Optional<T> empty(a) {
        @SuppressWarnings("unchecked")
        Optional<T> t = (Optional<T>) EMPTY;
        return t;
    }
    // This static method basically creates an object with a wrapper value that is not empty because of the assignment
   public static <T> Optional<T> of(T value) {
        return new Optional<>(value);
    }
    // This static method basically creates an empty object if the argument value is null, and a parameterized object if it is not
   public static <T> Optional<T> ofNullable(T value) {
        return value == null? empty() : of(value); }}Copy the code

Do a simple example to show the corresponding above

        // create an Optional object that wraps the object with an empty value
        Optional<String> optEmpty = Optional.empty();
        // create an Optional object that wraps the object with a non-empty value
        Optional<String> optOf = Optional.of("optional");
        // create an Optional wrapper object whose value can be empty or non-empty
        Optional<String> optOfNullable1 = Optional.ofNullable(null);
        Optional<String> optOfNullable2 = Optional.ofNullable("optional");
Copy the code

Now that we’ve done an overview of the internal methods for creating Optional objects, we’re going to start looking at Optional

2.2 optional.get () method (returns the value of the object)

The get() method returns an instance value of an option.

    public T get(a) {
        if (value == null) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }
Copy the code

That is, if value is not null, return, if value is null, throw an exception “No value present” example

        Person person=new Person();
        person.setAge(2);
        Optional.ofNullable(person).get();
Copy the code

2.3 Option.isPresent () (null)

The isPresent() method returns a Boolean value, true if the object is not empty, false if it is empty.

 public boolean isPresent(a) {
        returnvalue ! =null;
    }
Copy the code

A simple example shows:

       
        Person person=new Person();
        person.setAge(2);
        if (Optional.ofNullable(person).isPresent()){
        // Write non-null logic
        System.out.println("Not empty");
        }else{
         // Write to empty logic
         System.out.println("Empty");
        }
Copy the code

2.4 optional.ifPresent () method (reads null and returns function)

If the object is not empty, run the function body.

  public void ifPresent(Consumer<? super T> consumer) {
        // If value is not null, the accept body is run
        if(value ! =null)
            consumer.accept(value);
    }
Copy the code

See instances:

        Person person=new Person();
        person.setAge(2);
        Optional.ofNullable(person).ifPresent(p -> System.out.println("Age"+p.getAge()));
Copy the code

If the object is not empty, the age is printed, because NPE has already been done internally, so you don’t have to worry about null-pointer exceptions

2.5 optional.filter () method (filter objects)

The filter() method basically means that we take an object and filter it with criteria, returning the Optional object itself if the criteria are met, and empty Optional if not.

    public Optional<T> filter(Predicate<? super T> predicate) {
        Objects.requireNonNull(predicate);
        // Return this if null
        if(! isPresent())return this;
        else
        // Check whether the return itself is empty Optional
            return predicate.test(value) ? this : empty();
    }
Copy the code

A simple example:

        Person person=new Person();
        person.setAge(2);
        Optional.ofNullable(person).filter(p -> p.getAge()>50);
Copy the code

2.6 optional.map () method (re-wrap the object)

The map() method performs a quadratic operation on an object corresponding to the Funcation interface, encapsulates it into a new object and returns it in Optional:

 public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
        Objects.requireNonNull(mapper);
        // Return itself if null
        if(! isPresent())return empty();
        else {
        // Otherwise return Optional decorated with the method
            returnOptional.ofNullable(mapper.apply(value)); }}Copy the code

Examples show:

        Person person1=new Person();
        person.setAge(2);
        String optName = Optional.ofNullable(person).map(p -> person.getName()).orElse("The name is empty." ");
Copy the code

2.7 optional.flatmap () method (Optional object for secondary wrapping)

The map() method performs a secondary operation on the object corresponding to the Optional< Funcation > function interface, encapsulates it into a new object and returns it in Optional:

    public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
        Objects.requireNonNull(mapper);
        if(! isPresent())return empty();
        else {
            returnObjects.requireNonNull(mapper.apply(value)); }}Copy the code

Example:

        Person person=new Person();
        person.setAge(2);
        Optional<Object> optName = Optional.ofNullable(person).map(p -> Optional.ofNullable(p.getName()).orElse("The name is empty." "));

Copy the code

2.8 optional.orelse () method (returns an object with nothing)

If the object is empty, execute the value of the orElse method. If the object is not empty, return the source code of the write object.

    public T orElse(T other) {
    // If not empty, return value, if empty, return other
        returnvalue ! =null ? value : other;
    }
Copy the code

Example:

        Person person1=new Person();
        person.setAge(2);
        Optional.ofNullable(person).orElse(new Person("Xiao Ming".2));
Copy the code

2.9 optional. orElseGet() method (returns the Supplier object with nothing)

This is similar to orElse, except that the input parameter is the Supplier object, which is empty and returns the. Get () method of the passed object, or the current object if it is not empty:

    public T orElseGet(Supplier<? extends T> other) {
        returnvalue ! =null ? value : other.get();
    }
Copy the code

Example:

         Optional<Supplier<Person>> sup=Optional.ofNullable(Person::new);
        // Call the get() method, at which point the constructor of the object is called, i.e. the real object is obtained
         Optional.ofNullable(person).orElseGet(sup.get());
Copy the code

To be honest, I was confused about the Supplier object as well. I looked it up online and found that Supplier is also a way to create an object. In short, Suppiler is an interface that is lazy like Spring and does not take up memory once declared. The syntax for creating an object is Supplier supPerson= Person::new; Supperson.get () will do if needed

2.10 optional. orElseThrow() method (return exception if null)

This I personally in the actual practice also often use this method, method function is if empty, throw you define the exception, if not empty to return the current object, in the actual practice all exceptions must be handled well, for the readability of the code source:

    public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X {
        if(value ! =null) {
            return value;
        } else {
            throwexceptionSupplier.get(); }}Copy the code

Example: This post actual combat source code

// A simple query
        Member member = memberService.selectByPhone(request.getPhone());
        Optional.ofNullable(member).orElseThrow(() -> new ServiceException("No query related data"));
Copy the code

2.11 Comparative analysis of similarity methods

OrElse () is similar to orElseGet() and orElseThrow(). Map() is similar to flatMap(). So let me just summarize for you the similarities and differences between different methods orElse() and orElseGet() and orElseThrow()

OrElse (T object) orElseGet (Supplier < T > object) orElseThrow (exception)

Similarities and differences between Map () and orElseGet

Map (function function) flatmap (Optional< function > function)

How can I use the magic Optional option in real life

3. Actual combat scene reproduction

Scenario 1: Query an object in the Service layer, return it, determine whether it is empty, and process it

        // Query an object
        Member member = memberService.selectByIdNo(request.getCertificateNo());
        // use ofNullable and orElseThrow to judge and manipulate
        Optional.ofNullable(member).orElseThrow(() -> new ServiceException("No query related data"));
Copy the code

Scenario 2: We can define the return value in the DAO interface layer with Optional. For example: I use JPA, and so on

public interface LocationRepository extends JpaRepository<Location.String> {
Optional<Location> findLocationById(String id);
}
Copy the code

But in Service

public TerminalVO findById(String id) {
// This method is also wrapped Optional in the DAO layer
        Optional<Terminal> terminalOptional = terminalRepository.findById(id);
        // Use isPresent() directly to check whether isPresent() is null
        if (terminalOptional.isPresent()) {
        // Use the get() method to get the object value
            Terminal terminal = terminalOptional.get();
            // We can use BeanCopy instead of set to assign values
            TerminalVO terminalVO = BeanCopyUtils.copyBean(terminal, TerminalVO.class);
            // Call the DAO layer method to return the wrapped object
            Optional<Location> location = locationRepository.findLocationById(terminal.getLocationId());
            if (location.isPresent()) {
                terminalVO.setFullName(location.get().getFullName());
            }
            return terminalVO;
        }
        // Don't forget to throw an exception
        throw new ServiceException("This terminal does not exist");
    }
Copy the code

There are many more scenarios, including whether to return the current value or jump to another method body, and many more. If you are not experienced friends still want to learn, you can comment on it and I will reply to you

4.Optional use

Can Optional completely replace if? Example 1: What if I just want to determine whether a variable of an object is empty and make that determination?

Person person=new Person();
person.setName("");
persion.setAge(2);
// Common judgment
if(StringUtils.isNotBlank(person.getName())){
  // Execute code block with non-empty name
}
// Use Optional
Optional.ofNullable(person).map(p -> p.getName()).orElse("The name is empty." ");
Copy the code

I think this is a good example, but it’s a very simple judgment, if you use Optional you need to think about wrapping values, you need to think about code writing, you need to think about method calls, it’s only one line, but it’s not very readable, and if another programmer reads it, it’s not as obvious as if

5. Jdk1.9 optimized for Optional

Three methods were first added: OR (), ifPresentOrElse(), and stream(). Or () is similar to methods such as orElse in that it returns an object if it is not empty, or the default value in the or() method if it is empty. The ifPresentOrElse() method takes two arguments: a Consumer and a Runnable. If the object is not empty, the action Consumer is performed, otherwise Runnable is run. There are more OrElse judgments than ifPresent (). **stream()** Converts Optional to stream, returning a stream containing the value if there is a value, and an empty stream if there is no value.

Because this JDK1.9 Optional specific I did not test, but also found that there is a pretty good article has also let you understand jdK1.9 option optimization, I will not go into the details.

The author’s words

Mutual respect, mutual progress, thank you very much for everyone’s selfless spirit. Only in this way can we make more and more progress in IT in China. We are also willing to listen to the opinions and suggestions of more leaders with an open mind. I am your good friend Fan Yifan

If you think it’s good, I hope you can give me a thumbs up. Thank you very much! I want to make friends with you and make progress with you! A programmer who gets a little better every day