zoukankan      html  css  js  c++  java
  • 【Java8实战】使用Optional取代null

    在Java中对一个空对象进行操作时,便会抛出最常见的异常NullPointerException。为了改善这个问题,Java 8中提供了一个java.util.Optional<T>类型。Optional类的Javadoc描述如下:这是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。下面介绍Optional类的使用方法。 假如有一个像下面这样的类层次结构:

    class Department {
      private Employee employee;
      public Department(Employee employee) {
          this.employee = employee;
      }
      Employee getEmployee() {
          return employee;
      }
    }

    class Employee {
      private Girl girlFriend;
      public Employee(Girl girlFriend) {
          this.girlFriend = girlFriend;
      }
      Girl getGirlFriend() {
          return girlFriend;
      }
    }

    class Girl {
      private String name;
      public Girl(String name) {
          this.name = name;
      }
      String getName() {
          return name;
      }
    }

     

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

    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 "单身汪";
          }
          return "没有员工";
      }
      return "部门为空";
    }

     

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

    创建Optional

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

    创建一个空的Optional

    我们可以使用静态工厂方法Optional.empty,创建一个空的Optional对象:

    Optional<Department> department = Optional.empty();

     

    根据非空值创建Optional

    我们也可以使用静态工厂方法Optional.of来创建一个非空对象的Optional对象:

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

     

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

    创建可以为null的Optional

    使用静态工厂方法Optional.ofNullable,我们可以创建一个允许null值的Optional对象:

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

     

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

    Optional方法

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

    isPresent

    顾名思义,如果值存在返回true,否则返回false。如:

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

     

    get

    如果Optional有值则将其返回,否则抛出NoSuchElementException。下面举个抛出NoSuchElementException的例子:

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

     

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

    ifPresent

    如果Optional实例有值则为其调用Consumer(函数描述符为T -> void),否则不做处理。如:

    girl.ifPresent(g -> System.out.println("我有女朋友,名字是:" + g.getName()));

     

    orElse

    如果Optional实例有值则将其返回,否则返回orElse方法传入的参数。如:

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

     

    程序将输出There is no value present!

    orElseGet

    orElseGetorElse方法类似,orElse方法将传入的字符串作为默认值,而orElseGet方法可以接受Supplier(函数描述符为() -> T)来生成默认值。如:

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

     

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

    orElseThrow

    如果有值则将其返回,否则抛出Supplier接口创建的异常。如:

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

     

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

    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"));

     

    flatMap

    如果有值,为其执行Function函数返回Optional类型返回值,否则返回空Optional。flatMapmap方法类似,区别在于flatMap中的Function函数返回值必须是Optional。调用结束时,flatMap不会对结果用Optional封装。如:

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

     

    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

    实战

    介绍完Optional类的方法后,我们使用Optional改善一开始的代码:

    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);
    }

     

    整洁而又不失逼格。

  • 相关阅读:
    Beta 冲刺(1/7)
    福大软工 · 第十次作业
    11111111
    101
    7
    6
    5
    4
    p
    b2
  • 原文地址:https://www.cnblogs.com/7788IT/p/11625515.html
Copyright © 2011-2022 走看看