New way to write empty judgment in Java! Get rid of if else

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.

abe12f563fa5cf84437b43e3f1cb4a87.png

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.

51a0f59c23d7b77d8428435e5a86f23a.png

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, while the input parameter types of flapMap are Function>.

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

c759493a7583b1af536546e0913f2ebe.gif

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

b6d99532fd1c9cab1323ce4e51faac52.png

Programmer Xiaoyuan ID: DeveloperIT

Long press the QR code and follow with one click

5cf783c7812382c99a46404972e8b95a.gif

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