Java 8 Optional: gracefully avoid NPE

This article will describe in detail Optional classes, and how to use it to eliminate the code null checks. Before starting first look at what is NPE, and before Java 8 NPE is how to deal with the problem.

Null pointer exception (NullPointException, referred to as NPE) can be said that all Java programmers have encountered an exception, although from the beginning of design Java programmer trying to get out of Oliver pointer, but the pointer is indeed real, and Java designers can only make the pointer easier to use in the Java language, and can not be completely removed, so only the common right keyword null.

Avoid using null check

Null pointer exception is a runtime exception, for this type of exception if there is no clear approach, the best practice is to make the program as soon hang. When an exception does occur, the process is also very simple, add an if statement to determine where there is an abnormality. For example the following code:

public String bindUserToRole(User user) {
    if (user == null) {
        return;
    }

    String roleId = user.getRoleId();
    if (roleId == null) {
        return;
    }

    Role = roleDao.findOne(roleId);
    if (role != null) {
        role.setUserId(user.getUserId());
        roleDao.save(role);
    }
}

But such coping program will be more and more null judgment, a good program design, you should try to make the code appear less null keyword, so the introduction of Java 8 Optional NPE class to avoid problems, but also enhance the Code the aesthetics. But it is not an alternative to keyword null, but null for the determination provides a more elegant implementation, thus avoiding NPE problem.

Optional Class

In order to better solve problems and avoid common NPE, Java 8 introduced a new class java.util.Optional If the value exists, return, Optional value can be null call isPresent () method true, call the get () method can get the value.

Creating Optional objects

Optional class provides three methods for instantiating a class Optional objects, which are empty (), of (), ofNullable (), all three methods are static methods can be called directly.

empty () method is used to create an object without Optional values:

Optional<String> emptyOpt = Optional.empty();

empty () method to create an object of no value, if you call isPresent () method of emptyOpt variable returns false, call the get () method throws an exception NPE.

of () method creates Optional object using a non-null value:

String str = "Hello World";
Optional<String> notNullOpt = Optional.of(str);

ofNullable () method takes a null value to be:

Optional<String> nullableOpt = Optional.ofNullable(str);

If str is null, the resulting value is a no nullableOpt Optional objects.

Gets the value Optional object

If we want to get roleId User object property values, common way is direct access to:

String roleId = null;
if (user != null) {
    roleId = user.getRoleId();
}

Use map Optional provided () method can be implemented more simply:

Optional<User> userOpt = Optional.ofNullable(user);
Optional<String> roleIdOpt = userOpt.map(User::getRoleId);

Use orElse () method to get the value of

Optional class also contains methods for obtaining other values, these methods are:

  • orElse (): if the value is returned, otherwise a given value as a default
  • orElseGet (): and orElse () action similar manner, except that a different way of generating default values. The method accepts a Supplier <? Extends T> interface function parameter, for generating a default value
  • orElseThrow (): get a similar previously described () method is called when these two methods will throws NPE exception value is null, except that the method may specify the type of exception thrown

Let's look at the specific usage of these three methods:

String str = "Hello World";
Optional<String> strOpt = Optional.of(str);
String orElseResult = strOpt.orElse("Hello BeiJing");
String orElseGet = strOpt.orElseGet(() -> "Hello BeiJing");
String orElseThrow = strOpt.orElseThrow(
        () -> new IllegalArgumentException("Argument 'str' cannot be null or blank."));

Further, Optional The IfPresent also provides a class () method, the method receives a Consumer Function interface, typically used to print information to the console <super T?>:

Optional<String> strOpt = Optional.of("Hello World");
strOpt.ifPresent(System.out::println);

Use filter () method of filtering

filter () method can be used to judge whether an object Optional satisfies a given condition, the general conditions for filtering:

Optional<String> optional = Optional.of("[email protected]");
optional = optional.filter(str -> str.contains("wupx"));

In the above code, if the filter () method in the establishment of Lambda expressions, filter () method returns the current value Optional objects, otherwise, it returns a value of NULL Optional object.

About Optional use:

  • Try to avoid calling Optional object directly in the program get () and isPresent () method
  • Avoid using the attribute type declaration Optional entity class

Optional practice

Optional object has the above-mentioned three methods created, empty () method is relatively simple, mainly of () and ofNullable () method. When you identify an object can not be null, you should use of () method, otherwise, use ofNullable () method as much as possible, such as:

public static void method(Role role) {
    // 当Optional的值通过常量获得或者通过关键字 new 初始化,可以直接使用 of() 方法
    Optional<String> strOpt = Optional.of("Hello World");
    Optional<User> userOpt = Optional.of(new User());

    // 方法参数中role值不确定是否为null,使用 ofNullable() 方法创建
    Optional<Role> roleOpt = Optional.ofNullable(role);
}

Use orElse () method

return str != null ? str : "Hello World"

Determining whether the above code string str indicates empty, not empty returns, otherwise, it returns a constant. Use Optional classes can be expressed as:

return strOpt.orElse("Hello World")

Simplify the if-else

User user = ...
if (user != null) {
    String userName = user.getUserName();
    if (userName != null) {
        return userName.toUpperCase();
    } else {
        return null;
    }
} else {
    return null;
}

The above code can be simplified to:

User user = ...
Optional<User> userOpt = Optional.ofNullable(user);

return userOpt.map(User::getUserName)
            .map(String::toUpperCase)
            .orElse(null);

Precautions

Optional is a final class, does not implement any interface, Optional not be serialized, not as a category field (Field), so when we use the class attributes of the class definition package, if we define the sequence of the demand class then because Optional does not implement serializable interface, this time perform a sequence of operations will be a problem:

import java.util.Optional;
import lombok.Data;

@Data
public class User implements Serializable {
    private String name;
    private String gender;
    private Optional<String> phone; // 不能序列化
}

Getter methods implemented by themselves, do not make Lomok generated automatically, as follows:

import java.util.Optional;
import lombok.Data

@Data
public class User implements Serializable  {
    private String name;
    private String gender;
    private String phone;
    public Optional<String> getPhone() {
        return Optional.ofNullable(phone);
    }
}

to sum up

Optional classes in Java 8 allows us to functional programming approach to a null value, abandoned the nest before 8 Java needs a lot of if-else code blocks, the readability of the code has been greatly improved, but should be avoided Optional type declaration attribute entity class.

Guess you like

Origin www.cnblogs.com/wupeixuan/p/11722003.html