Small knowledge, big challenge! This paper is participating in theEssentials for programmers”Creative activities

When operating on an empty object in Java, NullPointerException, the most common exception, is thrown. To remedy this problem, Java 8 provides a java.util.Optional

type. The Javadoc for the Optional class is described as follows: This is a null-capable container object. The isPresent() method returns true if the value exists, and calling the get() method returns the object. Here’s how to use the Optional class. Suppose you have a class hierarchy like this:

class Department {
    private Employee employee;
    public Department(Employee employee) {
        this.employee = employee;
    }
    Employee getEmployee(a) {
        returnemployee; }}class Employee {
    private Girl girlFriend;
    public Employee(Girl girlFriend) {
        this.girlFriend = girlFriend;
    }
    Girl getGirlFriend(a) {
        returngirlFriend; }}class Girl {
    private String name;
    public Girl(String name) {
        this.name = name;
    }
    String getName(a) {
        returnname; }}Copy the code

The Department Department class contains an employee property of type EMPLOYEE, and the employee class contains the girlFriend property of type Girl. If we now want to obtain the girlfriend of an employee in our department, we usually obtain it as follows:

static String getGirlFriendName(Department department) {
    if(department ! =null) {
        Employee employee = department.getEmployee();
        if(employee ! =null) {
            Girl girl = employee.getGirlFriend();
            if(girl ! =null) {
                return girl.getName();
            }
            return "Single.";
        }
        return "No employees.";
    }
    return "Department is empty";
}
Copy the code

As you can see, every time a variable’s attribute is referenced, you must check whether the variable is null. Failure to do this check may result in a NullPointerException. We’ll use Optional to improve this layer of nested, verbose code.

Create the Optional

There are several ways to create an Optional object:

Create an empty Optional

We can create an empty Optional object using the static factory method optional. empty:

Optional<Department> department = Optional.empty();
Copy the code

Create Optional based ona non-null value

We can also use the static factory method option. of to create an Optional object that is not empty:

Optional<Employee> optEmployee = Optional.of(employee);
Copy the code

If Employee is empty, this code immediately throws a NullPointerException.

Create an Optional that can be null

Using the static factory method optional. ofNullable, we can create an Optional object that allows null values:

Optional<Employee> optEmployee = Optional.ofNullable(employee);
Copy the code

If Employee is empty, calling the GET method on it throws a NoSuchElementException.

Optional methods

The Optional class contains a number of methods, which are described below.

isPresent

As the name implies, return true if the value exists, false otherwise. Such as:

 Optional<Department> opt = Optional.ofNullable(department);
if(opt.isPresent()){
    System.out.println(opt.get().getEmployee());
}
Copy the code

get

Return Optional if it has a value, otherwise raise NoSuchElementException. Here is an example of a NoSuchElementException thrown:

try {
    Optional.empty().get();
} catch (Exception e) {
    e.printStackTrace();
}
Copy the code

Code will capture the Java. Util. NoSuchElementException: value the present No abnormalities.

ifPresent

Call Consumer (T -> void) for the Optional instance if it has a value, otherwise nothing is done. Such as:

girl.ifPresent(g -> System.out.println("I have a girlfriend whose name is:" + g.getName()));
Copy the code

orElse

Returns the Optional instance if it has a value, otherwise returns the argument passed in by the orElse method. Such as:

System.out.println(Optional.empty().orElse("There is no value present!"));
Copy the code

There is no value present! .

orElseGet

OrElseGet is similar to the orElse method in that the orElse method takes the string passed as the default value, whereas the orElseGet method can take Supplier (function descriptor () -> T) to generate the default value. Such as:

System.out.println(Optional.empty().orElseGet(() -> "There is no value present!"));
Copy the code

There is no value present! .

orElseThrow

If there is a value, it is returned; otherwise, an exception created by the Supplier interface is thrown. Such as:

try {
    Optional.empty().orElseThrow(NoSuchElementException::new);
} catch (Exception e) {
    e.printStackTrace();
}
Copy the code

Code will capture the Java. Util. NoSuchElementException: value the present No abnormalities.

map

If Optional has a value, call Function (T -> R) to get the return value. If the return value is not null, create an Optional containing the Function return value as the map method return value, otherwise return empty Optional.

Optional<String> upperName = name.map(String::toUpperCase);
System.out.println(upperName.orElse("No value found"));
Copy the code

flatMap

Function returns Optional if there is a value, otherwise empty Optional. FlatMap is similar to the map method except that the Function in flatMap must return Optional. At the end of the call, flatMap does not encapsulate the results with Optional. Such as:

upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
System.out.println(upperName.orElse("No value found"));
Copy the code

filter

The filter method filters the value of the Optional instance by passing Predicate (function descriptor T -> Boolean). Such as:

Optional<String> name = Optional.of("Jane");
Optional<String> LongName = name.filter((value) -> value.length() >= 3);
System.out.println(LongName.orElse("Name length less than 3 characters"));
Copy the code

The Jane method outputs.

In actual combat

After introducing the Optional class methods, we use Optional to improve the original code:

static String getGirlFriendName(Department department) {
    Optional<Department> opt = Optional.ofNullable(department);
    return opt.map(Department::getEmployee)
            .map(Employee::getGirlFriend)
            .map(Girl::getName)
            .orElseThrow(NoSuchElementException::new);
}
Copy the code

Neat and cool.