美文网首页
【JAVA8新特性】- 使用Optional取代null

【JAVA8新特性】- 使用Optional取代null

作者: lconcise | 来源:发表于2020-01-31 22:12 被阅读0次

Optional

在Java中对一个空对象进行操作时,便会抛出最常见的异常NullPointerException。为了改善这个问题,Java8中提供了一个java.util.Optional<T>类型。

Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在isPresent()方法会返回true,调用get()方法会返回该对象。

1. 示例1:

下面介绍Optional类的使用方法。 假如有一个像下面这样的类层次结构:

@Data
public class Department {

    private Employee employee;

    public Department(Employee employee) {
        this.employee = employee;
    }
}
@Data
class Employee{
    private Girl girlFriend;

    public Employee(Girl girlFriend) {
        this.girlFriend = girlFriend;
    }
}

@Data
class Girl{
    private String name;

    public Girl(String name) {
        this.name = name;
    }
}

部门Department类包含一个员工employee属性,类型为Employee,员工Employee类包含girlFriend属性,类型为Girl。假如现在要获取部门某个员工的女朋友,我们通常是这样获取的:

    public String getGirlFriend(Department department){
        if(department !=null){
            Employee employee = department.getEmployee();
            if(employee !=null){
                Girl girl = employee.getGirlFriend();
                if(girl!=null){
                    return girl.getName();
                }
                return "单身狗";
            }
            return "没有员工";
        }
        return "部门为空";
    }

可以看到,在每次引用变量的属性时,都要先判断变量是否为空,如果不做该检查将可能导致NullPointerException。下面我们将使用Optional来改善这种层层嵌套,啰嗦的代码。

    public String getGirlFriend2(Department department){
        Optional<Department> opt = Optional.ofNullable(department);
        return opt.map(Department::getEmployee)
                .map(Employee::getGirlFriend)
                .map(Girl::getName)
                .orElseThrow(NoSuchFieldError::new);

        // 如果发生NPE异常,则返回默认String "default"
        String girlName = opt.map(Department::getEmployee)
                .map(Employee::getGirl)
                .map(Girl::getName)
                .orElse("default");
    }

2. 示例2:

public class MainDemo {

    public static void main(String[] args) {
        Integer value1 = null;
        Integer value2 = new Integer(10);

        // Optional.ofNullable - 允许传递为null参数
        Optional<Integer> a = Optional.ofNullable(value1);
        // Optional.of - 如果传递的参数是null,抛出异常NullPointException
        Optional<Integer> b = Optional.of(value2);

        System.out.println(sum(a, b));
    }

    private static Integer sum(Optional<Integer> a, Optional<Integer> b) {
        // Optional.isPresent - 判断值是否存在
        System.out.println("第一个参数值存在:" + a.isPresent());
        System.out.println("第二个参数值存在:" + b.isPresent());

        // Optional.orElse - 如果值存在,返回它,否则返回默认值
        Integer value1 = a.orElse(new Integer(0));

        Integer value2 = b.get();

        return value1 + value2;
    }
}

输出:

第一个参数值存在:false
第二个参数值存在:true
10

下面我们来具体学习下Optional:

创建Optional

创建一个Optional对象有好几种方式:

  1. 创建一个空的Optional
    我们可以使用静态工厂方法Optional.empty,创建一个空的Optional对象:
Optional<Department> department = Optional.empty();
  1. 根据非空值创建Optional
    我们也可以使用静态工厂方法Optional.of来创建一个非空对象的Optional对象:
Optional<Employee> optEmployee = Optional.of(employee);

如果employee为空,这段代码会立即抛出一个NullPointerException。

  1. 创建可以为null的Optional
    使用静态工厂方法Optional.ofNullable,我们可以创建一个允许null值的Optional对象:
Optional<Employee> optEmployee = Optional.ofNullable(employee);

如果employee为空,对其调用get方法将抛出NoSuchElementException。

Optional方法

Optional类包含了许多方法,下面介绍这些方法的使用。

  1. isPresent
    顾名思义,如果值存在返回true,否则返回false。如:
 Optional<Department> opt = Optional.ofNullable(department);
if(opt.isPresent()){
    System.out.println(opt.get().getEmployee());
}
  1. get
    如果Optional有值则将其返回,否则抛出NoSuchElementException。下面举个抛出NoSuchElementException的例子:
try {
    Optional.empty().get();
} catch (Exception e) {
    e.printStackTrace();
}

代码将捕获到 java.util.NoSuchElementException: No value present 异常。

  1. ifPresent
    如果Optional实例有值则为其调用Consumer(函数描述符为T -> void),否则不做处理。如:
girl.ifPresent(g -> System.out.println("我有女朋友,名字是:" + g.getName()));
  1. orElse
    如果Optional实例有值则将其返回,否则返回orElse方法传入的参数。如:
System.out.println(Optional.empty().orElse("There is no value present!"));

程序将输出There is no value present!。

  1. orElseGet
    orElseGet与orElse方法类似,orElse方法将传入的字符串作为默认值,而orElseGet方法可以接受Supplier(函数描述符为() -> T)来生成默认值。如:
System.out.println(Optional.empty().orElseGet(() -> "There is no value present!"));

程序同样输出There is no value present!。

  1. orElseThrow
    如果有值则将其返回,否则抛出Supplier接口创建的异常。如:
try {
    Optional.empty().orElseThrow(NoSuchElementException::new);
} catch (Exception e) {
    e.printStackTrace();
}

代码将捕获到 java.util.NoSuchElementException: No value present 异常。
7.map
如果Optional有值,则对其执行调用Function函数描述符为(T -> R)得到返回值。如果返回值不为null,则创建包含Function回值的Optional作为map方法返回值,否则返回空Optional。

Optional<String> upperName = name.map(String::toUpperCase);
System.out.println(upperName.orElse("No value found"));
  1. flatMap
    如果有值,为其执行Function函数返回Optional类型返回值,否则返回空Optional。flatMap与map方法类似,区别在于flatMap中的Function函数返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。如:
upperName = name.flatMap((value) -> Optional.of(value.toUpperCase()));
System.out.println(upperName.orElse("No value found"));
  1. filter
    filter个方法通过传入Predicate(函数描述符为T -> Boolean)对Optional实例的值进行过滤。如:
Optional<String> name = Optional.of("Jane");
Optional<String> LongName = name.filter((value) -> value.length() >= 3);
System.out.println(LongName.orElse("名字长度小于3个字符"));

方法输出Jane。

相关文章

网友评论

      本文标题:【JAVA8新特性】- 使用Optional取代null

      本文链接:https://www.haomeiwen.com/subject/tnrdactx.html