首页 > 编程语言 > 详细

java8 Optional理解及示例

时间:2020-03-08 15:48:48      阅读:63      评论:0      收藏:0      [点我收藏+]

大量判空的代码

实际中,对象不判空会导致空指针异常。

为了规避为指针,不得不写出这种非常冗长又丑陋的空指针判断。

public void tooMuchNull(Worker worker) {
    if (worker != null) {
        Address address=worker.getAddress();
        if (address != null) {
            String city=address.getCity();
        }
    }
}

Optional<T>

Optional<T>包含的对象value可能非null,也可能为null。

常建的构建Optional<T>对象的方法,有ofNullable(T value)、of(T value)。

构建时,最终都会调用Optional的构造方法Optional(T value)。

而常见的判断Optional结果的方法有,orElse()、ifPresent()、get()、empty()、map()、flatMap()。

api图

如下图所示:
技术分享图片

代码示例:

  • orElse():
/**
 * orElse(默认值),如果Optional<T>封装的对象不存在值,则返回默认值。
 */
public void orElseDemo() {
//      Worker worker1=new Worker("123",18,"lin");
    Worker worker1 = null;
    Worker worker2 = new Worker("456", 28, "chen");
    //如果worker1不为null,则orElse返回worker1,否则返回默认值worker2
    Worker result = Optional.ofNullable(worker1).orElse(worker2);
    //相当于以下代码:
//      if (worker1 != null) {
//          result = worker1;
//      } else {
//          result = worker2;
//      }
    System.out.println(result.getName() + "," + result.getAge());
}
  • orElseGet():
/**
 * orElseGet(),如果Optional<T>封装的对象不存在值,则执行Supplier函数式。
 * orElseGet(Supplier<? extends T> other),返回的类型必须和Optional封装的对象类型一致。
 */
public void ofElseGetDemo() {
    String name1 = null;
    String name2 = "lin";
    //orElseGet(Supplier<? extends T> other),返回的类型必须和Optional封装的对象类型一致。
    String result = Optional.ofNullable(name1).orElseGet(OptionalDemo::supplier);
    System.out.println(result);
}

public String supplier() {
    return "orElseGet(Supplier)";
}
  • of():
/**
 * of(对象),如果封装的对象为空,则会报出空指针异常
 */
public void ofDemo() {
//      Worker worker1=new Worker("123",18,"lin");
    Worker worker1 = null;
    Worker worker2 = new Worker("456", 28, "chen");
    Worker result = Optional.of(worker1).orElse(worker2);
    System.out.println(result.getName() + "," + result.getAge());
}
  • isPresent():
/**
 * isPresent()表示如果Optional<T>封装的对象不为空,就返回true。
 */
public void isPresentDemo() {
    Worker worker1 = new Worker("123", 18, "lin");
    Optional<Worker> workerOpt = Optional.ofNullable(worker1);
    //这种写法比较丑,可以直接用下面的ifPresent()方法代替。
    boolean isPresent = workerOpt.isPresent();
    if (isPresent) {
        System.out.println(workerOpt.get().getName());
    }
    //以上代码,相当于:
//      if (worker1 != null) {
//          System.out.println(worker1.getName());
//      }
}
  • ifPresent():
/**
 * ifPresent()表示如果对象不为null,则会执行对应的lambda语句。
 */
public void ifPresentDemo() {
//      Address address=new Address("中国","广东","深圳");
//      Worker worker1=new Worker("123",18,"lin",address);
    Worker worker1 = new Worker("123", 18, "lin");
//      Worker worker1=null;
    List<String> nameList = new ArrayList<>();
    Optional.ofNullable(worker1).ifPresent(worker -> nameList.add(worker.getName()));
    //上面这句代码的作用相当于以下注释的代码:
//      if (worker1 != null) {
//          nameList.add(worker1.getName());
//      }
    nameList.forEach(System.out::println);
}
  • flatMap():
/**
 * flatMap(),如果Optional封装对象不为空,就会执行对应的mapping函数,返回Optional类型的值。
 * 否则就返回一个空的Optional对象。
 */
public void flatMapDemo() {
    Address address = new Address("中国", "广东", "深圳");
    Worker worker = new Worker("123", 18, "lin", address);
    //默认值为"default",有没有更好的选择?
    String city = Optional.ofNullable(worker)
            .flatMap(Worker::getAdress)
            .flatMap(Address::getCity)
            .orElse("default");
    System.out.println(city);
}
  • orElseThrow():
/**
 * orElseThrow(),如果Optional封装的对象为空,就会抛出对应的异常。
 */
public void orElseThrowDemo() {
//      Worker worker = new Worker("123", 18, "lin");
    Worker worker = null;
    Worker result = Optional.ofNullable(worker)
            .orElseThrow(IllegalArgumentException::new);
    System.out.println(result.getName());
}
  • filter():
public void filterDemo() {
    Worker worker = new Worker("123", 18, "lin");
    Optional<Worker> result = Optional.ofNullable(worker)
            .filter(worker1 -> worker1.getAge() > 20);
    //如果符合条件(比如,年龄大于20)则为true,不符合则为false
    System.out.println(result.isPresent());
}

区别:

  • of() 和 ofNullable() 的区别:

这两个方法都可以创建包含值的 Optional。
不同之处在于如果你把 null值作为参数传递进ofNullable(),而传递null作为参数时,of() 方法会抛出 NullPointerException。

  • orElse()和orElseGet()的区别:
    orElse(默认值),表示如果有值则返回该值,否则返回传递给它的默认值。

orElseGet(lambda表达式)会在有值的时候返回值,如果没有值,它会执行作为参数传入的函数式接口(返回类型必须和Optional封装的对象是同一种类型),并将返回其执行结果。

需要特别注意的是:

Optional的orElse()若方法不是纯计算型的,有与数据库交互或者远程调用的,都应该使用orElseGet() 。

orElse()无论前面Optional容器是null还是non-null,都会执行orElse里的方法,orElseGet()并不会。

详情参见:https://blog.csdn.net/weixin_30437337/article/details/95443798

  • isPresent()和ifPresent()的区别:

看方法名is开头,就可以知道isPresent()返回的是布尔值。而ifPresent()则是如果对应的值存在,就会执行函数式接口。

  • flatMap()和map()的区别:

值不为空时,两者都会执行参数中的函数式接口。

map() 对值调用参数中的函数,然后将返回的值包装在 Optional 中。

值为空时,flatMap()还会返回一个空的Optional。

可以重构的示例:

回头看一下开头的代码,如下:

public void tooMuchNull(Worker worker) {
    if (worker != null) {
        Address address=worker.getAddress();
        if (address != null) {
            String city=address.getCity();
        }
    }
}

下面尝试用Optional改写。

重写getter()

重写getter,返回Optional对象。

public class User {
    private Address address;

    public Optional<Address> getAddress() {
        return Optional.ofNullable(address);
    }

    // ...
}

优化

重写完getter后,上面的例子,可以用Optional改写为:

public void preventNullPointer() {
    User user = new User("anna@gmail.com", "1234");

    String result = Optional.ofNullable(user)
      .flatMap(u -> u.getAddress())
      .flatMap(a -> a.getCity())
      .orElse("default");

}

再进一步简写成:

String city = Optional.ofNullable(worker)
        .flatMap(Worker::getAdress)
        .flatMap(Address::getCity)
        .orElse("default");

使用Optional要注意:

  • Optional 主要用作返回类型。

  • Optional不能作为入参的参数.

  • Optional不会序列化,不要直接作为对象属性。

  • Optional不要用于集合操作。空集合请使用Collections.emptyList()。

代码地址:

https://github.com/firefoxer1992/JavaDemo/tree/master/src/main/java/com/java8

参考资料:

https://www.cnblogs.com/zhangboyu/p/7580262.html

java8 Optional理解及示例

原文:https://www.cnblogs.com/expiator/p/12442629.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!