preface

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 short, Opitonal class is provided by Java in order to solve the problem that you usually determine whether an object is empty, will use null! =obj exists in such a way.

NPE (Null Pointer Exception) and Optional can make code simpler, more readable and more efficient. General judgment:

// Object Person attributes have name, age Person =new Person(); If (null==person){return "person is null"; } return person;Copy the code

Optional:

// Object Person attributes have name, age Person =new Person(); Return Optional. OfNullable (person). OrElse (" 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() { } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { 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 final Optional<? > EMPTY = new Optional<>(); private final T value; Private Optional() {this.value = null; } private Optional(T value) { this.value = Objects.requireNonNull(value); Public static<T> Optional<T> empty() {@suppressWarnings ("unchecked") public static<T> Optional<T> Empty () {@suppressWarnings ("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } 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, if it is not null, 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

Optional<String> optEmpty = option.empty (); Optional<String> optOf = option. of(" Optional "); // create Optional object Optional<String> optOfNullable1 = option.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. The get () method

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

public T get() {
  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 Optional. IsPresent () method

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

public Boolean isPresent() { return value ! = null; }Copy the code

A simple example shows:

Person person=new Person(); person.setAge(2); If (option.ofNullable (person).ispresent ()){// Write the null logic system.out.println (" null "); } else{// write empty logic system.out.println (" empty "); }Copy the code

2.4 Optional. IfPresent () method

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

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

See instances:

Person person=new Person(); person.setAge(2); Option.ofnullable (person).ifPresent(p -> system.out.println (" age "+ p.gettage ())));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. The filter () method

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 (! isPresent()) return this; Else // Determine 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. The map () method

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 yourself if (! isPresent()) return empty(); Option.ofnullable (mapper.apply(value)); else {// Otherwise return option.ofNullable (mapper.apply(value)); }}Copy the code

Examples show:

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

2.7 Optional. FlatMap () method

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 {
        return Objects.requireNonNull(mapper.apply(value));
    }
}
Copy the code

Example:

Person person=new Person(); person.setAge(2); OptName = option.ofnullable (person).map(p -> option.ofnullable (p.getName()).orelse ("name is empty "));Copy the code

2.8 Optional. OrElse () method

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 return value! = null ? value : other; }Copy the code

2.9 Optional. OrElseGet () method

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) { return value ! = null ? value : other.get(); }Copy the code

Example:

Optional<Supplier<Person>> sup=Optional.ofNullable(Person::new); Option.ofnullable (person).orelseget (sup.get());Copy the code

Supplier is also a way to create objects. Simply put, Suppiler is an interface that is lazy like Spring and does not consume memory after being declared.

The constructor is called to create the object only after the get() method is executed. The syntax for creating the object is Supplier supPerson= Person::new; Supperson.get () will do if needed

2.10 Optional. OrElseThrow () method

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 {
        throw exceptionSupplier.get();
    }
}
Copy the code

Example: This post actual combat source code

/ / a simple query Member Member. = memberService selectByPhone (request. The getPhone ()); Option.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(), and map() is similar to flatMap().

Ha ha ha don’t worry, all come from this step, I will give you a summary of the differences and similarities of different methods

Similarities and differences between orElse() and orElseGet() and orElseThrow()

If the object is not empty, the object is returned. If the object is empty, the corresponding parameter in the method body is returned. So we can see that the parameters in the three method bodies are different

  • OrElse (T object)

  • OrElseGet (Supplier < T > object)

  • OrElseThrow (exception)

Similarities and differences between Map () and orElseGet

  • Method effect is similar, the method parameters are wrapped twice, and return, the input parameter is different

  • 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 to determine whether it is empty and process it

/ / query an object Member Member. = memberService selectByIdNo (request) getCertificateNo ()); Option.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 wrapped with Optional<Terminal> terminalOptional = terminalRepository.findById(id); / / directly using the isPresent () to determine whether is empty if (terminalOptional. IsPresent ()) {/ / using the get () method to obtain object values Terminal Terminal = terminalOptional. The get ();  TerminalVO = beancopyutils.copybean (terminal, TerminalVO. Class); // TerminalVO = beancopyutils.copybean (terminal, TerminalVO. / / call the dao layer method returns after packing objects Optional < Location > Location = locationRepository. FindLocationById (terminal) getLocationId ()); if (location.isPresent()) { terminalVO.setFullName(location.get().getFullName()); } return terminalVO; } // Don't forget to throw new ServiceException(" This terminal doesn't exist "); }Copy the code

4.Optional use

Can Optional completely replace if?

I’m sure that’s what you might think after you use Optional, and the answer is no. Here’s the simplest one:

Example 1:

What if I just want to determine whether a variable of the object is empty and make that determination?

Person person=new Person(); person.setName(""); persion.setAge(2); If (stringutils.isnotBlank (person.getName())){// If (stringutils.isnotBlank (person.getName())){// If (stringutils.isnotBlank (person.getName()))} P.g etName ()). OrElse (" the name is empty ");Copy the code

I think this is a good example of that, but it’s a very simple judgment.

If we use Optional we also have to think about wrapping values, we have to think about code writing, we have to think about method calls.

Although it is only one line, it is not very readable. If other programmers read it, I think it is 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 the stream containing the value if there is a value, and the 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.