谈谈Optional如何避免空指针异常

在实际的开发过程中,空指针异常是我们最讨厌的异常,为了防止空指针异常,我们不得不在代码里面写大量的非空判断。

伟大的计算机科学Tony Hoare曾经写到:“我认为null引用从1965年被创造出来导致了十亿美元的损失。当初使用null引

用对我最大的诱惑是它实现起来方便”,但是在JAVA8中引入了一个新的类Optional,用于专门解决非空判断这个问题。

先举一个之间如何防止空指针异常而多次的对对象进行非空判断.

public static String getInsuranceDeepName(Person person){
    if(person!=null){
        Car car = person.getCar();
        if(car!=null){
            Insurance insurance = car.getInsurance();
            if(insurance!=null){
                return insurance.getName();
            }
        }
    }
    return "unknow";
}
public static String getInsuranceNameByMultExit(Person person){
    String defaultValue = "unknow";
    if(null==person)
        return defaultValue;
    Car car = person.getCar();
    if(null==car)
        return defaultValue;
    Insurance insurance = car.getInsurance();
    if(null==insurance)
        return defaultValue;

    return insurance.getName();
}

上面两个方法都是为了获取person对象下的car属性对象的insurance属性对象的的name。是不是感觉很麻烦。并且代码

的整个变得非常丑陋。但是我们又不得不通过这样的判断来确保系统运行时不会出现空指针异常。如果我们的业务代码

中出现大量的这种空引用判断简直是让人恼火,也会导致我们的代码的可读性会很差。

JAVA8引入一个新类叫做java.util.Optional,这个类的设计灵感来源于Haskell语言和Scala语言。这个类可以包含任意

值,包括null。

1.创建optional对象

empty() 方法用于创建一个没有值的Optional对象:

Optional emptyOpt = Optional.empty();

of() 方法使用一个非空的值创建Optional对象:

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

ofNullable() 方法接收一个可以为null的值:

Optional nullableOpt = Optional.ofNullable(str);

一般用ofNullable而不用of;

2.判断Null

isPresent()

如果创建的对象没有值,调用isPresent()方法会返回false,调用get()方法抛出NullPointerException异常。

3.获取对象

get()

4.使用map提取对象的值

如果我们要获取User对象中的roleId属性值,常见的方式是直接获取:

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

使用Optional中提供的map()方法可以以更简单的方式实现:

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

5.使用orElse方法设置默认值

Optional类还包含其他方法用于获取值,这些方法分别为:

  • orElse():如果有值就返回,否则返回一个给定的值作为默认值;
  • orElseGet():与orElse()方法作用类似,区别在于生成默认值的方式不同。该方法接受一个Supplier函数式接口参数,用于生成默认值;
  • orElseThrow():与前面介绍的get()方法类似,当值为null时调用这两个方法都会抛出NullPointerException异常,区别在于该方法可以指定抛出的异常类型。
String str = "Hello World";
Optional strOpt = Optional.of(str);
String orElseResult = strOpt.orElse("Hello Shanghai");
String orElseGet = strOpt.orElseGet(() -> "Hello Shanghai");
String orElseThrow = strOpt.orElseThrow(
 () -> new IllegalArgumentException("Argument 'str' cannot be null or blank."));

6.使用filter()方法过滤

filter()方法可用于判断Optional对象是否满足给定条件,一般用于条件过滤:

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

在上面的代码中,如果filter()方法中的Lambda表达式成立,filter()方法会返回当前Optional对象值,否则,返回一个值为空的Optional对象。

7.使用建议

  1. 尽量避免在程序中直接调用Optional对象的get()和isPresent()方法;
  2. 避免使用Optional类型声明实体类的属性;

8.正确示例

orElse()方法的使用

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

上面的代码表示判断字符串str是否为空,不为空就返回,否则,返回一个常量。使用Optional类可以表示为:

return strOpt.orElse("Hello World")

简化if-else

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

上面的代码可以简化成:

User user = ...
Optional userOpt = Optional.ofNullable(user);
return user.map(User::getUserName)
 .map(String::toUpperCase)
 .orElse(null);

你可能感兴趣的:(谈谈Optional如何避免空指针异常)