Hello everyone, I am Brother Yue.
Awesome Plus, another tool is about to explode!
At the beginning of the article, let’s talk about the NPE problem. The NPE problem is the NullPointerException that we often encounter in development. Assume that we have two classes, and their UML class diagrams are as shown below.
In this case, there is the following code
user.getAddress().getProvince();
This way of writing may cause a NullPointerException when user is null. In order to solve this problem, the following writing method is adopted
if(user!=null){ Address address = user.getAddress(); if(address!=null){ String province = address.getProvince(); } }
This kind of writing is relatively ugly. In order to avoid the above-mentioned ugly writing, make the ugly design elegant. JAVA8 provides the Optional class to optimize this writing method, which will be explained in detail in the following text.
API Introduction
Let’s first introduce the API. Unlike other articles, this article uses an analogy and combines it with the source code. Unlike other articles, APIs are listed one by one, making people unable to find the key points.
1. Optional(T value),empty(),of(T value),ofNullable(T value)
There is a correlation between these four functions, so they are put together for memory.
Let me first explain, Optional(T value)
, that is, the constructor, it has private permissions and cannot be called externally. The remaining three functions are public permissions for us to call. Then, the essence of Optional is that it stores a real value internally, and when it is constructed, it directly determines whether its value is empty. Okay, so it’s a bit abstract. Go directly to the source code of the Optional(T value)
constructor, as shown in the figure below
An aside, if you are planning to interview and change jobs in the near future, it is recommended to answer questions online at ddkk.com, covering 10,000+ Java interview questions, covering almost all mainstream technical interview questions, and the most comprehensive 500 sets of technology stacks on the market, which are high-quality products. A series of tutorials, available for free.
Then, the source code of of(T value) is as follows
public static <T> Optional<T> of(T value) { return new Optional<>(value); }
In other words, the of(T value) function calls the constructor internally. Based on the source code of the constructor we can draw two conclusions:
-
The Optional object constructed through the
of(T value)
function will still report a NullPointerException when the Value value is empty. -
When the Value value is not empty, the Optional object constructed through the
of(T value)
function can be constructed normally.
In addition, the Optional class also maintains an object with a value of null, which probably looks like the following
public final class Optional<T> { //Omit.... private static final Optional<?> EMPTY = new Optional<>(); private Optional() { this.value = null; } //Omit... public static<T> Optional<T> empty() { @SuppressWarnings("unchecked") Optional<T> t = (Optional<T>) EMPTY; return t; } }
Then, the function of empty()
is to return the EMPTY object.
Now that we have laid the foundation for so much, we can talk about the role of ofNullable(T value)
. Let’s go to the source code.
public static <T> Optional<T> ofNullable(T value) { return value == null ? empty() : of(value); }
Okay, everyone should understand what it means. Compared with of(T value)
, the difference is that when value is null, of(T value) will report NullPointerException; ofNullable(T value)
will not throw Exception, ofNullable(T value)
directly returns an EMPTY
object.
An aside, if you are preparing for an interview to change jobs in the near future, it is recommended to answer questions online at ddkk.com, covering 10,000+ Java interview questions, covering almost all mainstream technical interview questions, and the most comprehensive 500 sets of technology stacks on the market, which are high-quality products. A series of tutorials, available for free.
Does that mean that we only use the ofNullable
function in the project instead of the of function?
No, as long as something exists, it naturally has value. When we are running, we don’t want to hide NullPointerException
. Instead, it needs to be reported immediately, in which case the Of function is used. But I have to admit that such scenes are really rare. The blogger has only used this function when writing junit test cases.
2. orElse(T other), orElseGet(Supplier other) and orElseThrow(Supplier exceptionSupplier)
These three functions are put together for memory, and are all called when the value passed in the constructor is null. The usage of orElse
and orElseGet
is as follows, which is equivalent to giving a default value when the value is null:
@Test public void test() { User user = null; user = Optional.ofNullable(user).orElse(createUser()); user = Optional.ofNullable(user).orElseGet(() -> createUser()); } public User createUser(){ User user = new User(); user.setName("zhangsan"); return user; }
The difference between these two functions: when the user value is not null, the orElse
function will still execute the createUser() method, while the orElseGet
function will not execute the createUser() method. , everyone can test it by themselves.
As for orElseThrow, when the value is null, an exception is thrown directly. The usage is as follows
User user = null; Optional.ofNullable(user).orElseThrow(()->new Exception("User does not exist"));
3. map(Function mapper) and flatMap(Function> mapper)
These two functions are placed in a set of memories. What these two functions do is convert values.
Directly upload the source code
public final class Optional<T> { //Omit.... 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)); } } //Omit... 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)); } } }
There is no difference between these two functions in the function body. The only difference is the input parameters. The input parameter types accepted by the map function are Function super T, ? extends U>
, while the input parameter types of flapMap are Function super T, Optional>
.
In terms of specific usage, for map:
If the User structure is as follows
public class User { private String name; public String getName() { return name; } }
At this time, the way to write the name is as follows:
String city = Optional.ofNullable(user).map(u-> u.getName()).get();
For flatMap:
If the User structure is as follows
public class User { private String name; public Optional<String> getName() { return Optional.ofNullable(name); } }
At this time, the way to write the name is as follows:
String city = Optional.ofNullable(user).flatMap(u-> u.getName()).get();
4. isPresent() and ifPresent(Consumer consumer)
These two functions are memorized together. isPresent
determines whether the value is empty, and ifPresent
performs some operations when the value is not empty. The source code of these two functions is as follows
An aside, if you are preparing for an interview to change jobs in the near future, it is recommended to answer questions online at ddkk.com, covering 10,000+ Java interview questions, covering almost all mainstream technical interview questions, and the most comprehensive 500 sets of technology stacks on the market, which are high-quality products. A series of tutorials, available for free.
public final class Optional<T> { //Omit.... public boolean isPresent() { return value != null; } //Omit... public void ifPresent(Consumer<? super T> consumer) { if (value != null) consumer.accept(value); } }
What needs additional explanation is that everyone must not put
if (user != null){ // TODO: do something }
written as
User user = Optional.ofNullable(user); if (Optional.isPresent()){ // TODO: do something }
Because written this way, the code structure is still ugly. The blogger will give you the correct way to write it later.
As for ifPresent(Consumer super T> consumer)
, the usage is also very simple, as shown below
Optional.ofNullable(user).ifPresent(u->{ // TODO: do something });
5. filter(Predicate predicate)
Not much to say, just go to the source code
public final class Optional<T> { //Omit.... Objects.requireNonNull(predicate); if (!isPresent()) return this; else return predicate.test(value) ? this : empty(); }
The filter method accepts a Predicate
to filter the values contained in Optional
. If the contained values meet the conditions, then this Optional is still returned; otherwise, Optional.empty is returned.
.
Usage is as follows
Optional<User> user1 = Optional.ofNullable(user).filter(u -> u.getName().length()<6);
As shown above, if the length of user’s name is less than 6, it is returned. If it is greater than 6, an EMPTY object is returned.
An aside, if you are preparing for an interview to change jobs in the near future, it is recommended to answer questions online at ddkk.com, covering 10,000+ Java interview questions, covering almost all mainstream technical interview questions, and the most comprehensive 500 sets of technology stacks on the market, which are high-quality products. A series of tutorials, available for free.
Practical use
Example 1
in function method
previous writing method
public String getCity(User user) throws Exception{ if(user!=null){ if(user.getAddress()!=null){ Address address = user.getAddress(); if(address.getCity()!=null){ return address.getCity(); } } } throw new Excpetion("Value error"); }
JAVA8 writing method
public String getCity(User user) throws Exception{ return Optional.ofNullable(user) .map(u-> u.getAddress()) .map(a->a.getCity()) .orElseThrow(()->new Exception("fetch error")); }
Example 2
For example, in the main program
previous writing method
if(user!=null){ dosomething(user); }
JAVA8 writing method
Optional.ofNullable(user) .ifPresent(u->{ dosomething(u); });
Example 3
previous writing method
public User getUser(User user) throws Exception{ if(user!=null){ String name = user.getName(); if("zhangsan".equals(name)){ return user; } }else{ user = new User(); user.setName("zhangsan"); return user; } }
java8 writing method
public User getUser(User user) { return Optional.ofNullable(user) .filter(u->"zhangsan".equals(u.getName())) .orElseGet(()-> { User user1 = new User(); user1.setName("zhangsan"); return user1; }); }
Other examples are not listed one by one. However, using this chain programming, although the code is more elegant. However, the logic is not that obvious and the readability is reduced. You can use it as appropriate according to the situation in your project.
Thank you for reading carefully. If you like this article, please click “Reading” or forward it to your circle of friends so that more people can see it
Programmer Xiaoyuan ID: DeveloperIT
Long press the QR code and follow with one click
The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Java skill treeControl execution processif-else137742 people are learning the system