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
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.