java8函数式编程学习(四)- Optional
4. Optional
4.1 概述
我们在编写代码的时候出现最对的就是空指针异常。所以我们需要在各种情况下做非空判断。
List<Author> authors = StreamDemo.getAuthors();
if (CollectionUtils.isNotEmpty(authors)) {
Author author = authors.get(0);
if (null != author) {
System.out.println(author.getName());
}
}
尤其对象中的属性还是一个对象时,这种判断会更多。而过多的判断语句让我们的代码显得臃肿不堪。
所以JDK8引入了Optional,养成了使用Optional的习惯后你可以写出更优雅的代码来避免空指针异常。
并且在很多函数式编程相关的API也用到了Optional。
4.2 使用
基础方法
public static Author getAuthor() {
Author author = new Author(1L, "蒙多", 33, "测试人1", null);
return author;
}
public static Optional<Author> getAuthorOptional() {
Author author = new Author(1L, "蒙多", 33, "测试人1", null);
return Optional.ofNullable(author);
}
4.2.1 创建对象
Optional就好像是包装类,可以把我们的具体数据封装到Optional对象内部。然后我们去使用Optional中封装好的方法操作数据就可以非常优雅的避免空指针。
// 例子:我们一般使用Optional的静态方法ofNullable来把数据封装成Optional对象,传入的参数是否为null都不会出现问题
Author author = getAuthor();
Optional<Author> authorOptional = Optional.ofNullable(author);
authorOptional.ifPresent(authorBean -> System.out.println(authorBean));
// 一般情况都是返回Optional对象的 优化后
Optional<Author> authorOptional1 = getAuthorOptional();
authorOptional1.ifPresent(authorBean -> System.out.println(authorBean));
// 在实际开发中我们的数据大都是从数据库中获取的,Mybatis从3.5版本开始已经可以支持Optional了。
// 我们可以直接把dao方法的返回值类型定义成Optional类型,Mybatis会自己把数据封装成Optional对象返回,封装过程不需要我们自己来操作。
// 如果你确定一个对象不是空的则可使用Optional的静态方法of来把数据封装成Optional对象。
Author author1 = new Author();
Optional<Author> author1Optional = Optional.of(author1);
// 一定要注意,使用of的时候传入的参数必须不为null(会出现空指针异常)。
// 如果一个方法的返回值类型是Optional类型,而如果判断发现返回值为null,则需要把null封装成Optional对象返回,调用Optional的静态方法empty()。
Optional.empty();
4.2.2 安全消费值
我们获取到一个Optional对象后肯定需要对其中的数据进行使用,这时候我们可以用ifPresent方法来消费其中的值。
这个方法会判断其内封装的数据是否为空,不为空时才会执行具体的消费代码,这样使用起来就更加安全。
// 例子
Author author = getAuthor();
Optional<Author> authorOptional = Optional.ofNullable(author);
authorOptional.ifPresent(authorBean -> System.out.println(authorBean));
4.2.3 获取值
如果我们想获取值自行处理可以使用get方法获取,但是不推荐。因为Optional内部的数据为空是会出现异常。
// 例子
Optional<Author> authorOptional = getAuthorOptional();
Author author1 = authorOptional.get();
4.2.4 安全获取值
如果我们想安全获取值,不推荐使用get方法,而是使用Optional提供的一下方法。
// orElseGet
// 获取数据并设置如果数据为空时的默认值,如果数据不为空就可以获取到,如果数据为空时则根据你传入的参数来创建对象作为默认值返回。
Optional<Author> authorOptional = getAuthorOptional();
Author author = authorOptional.orElseGet(() -> new Author());
// orElseThrow
// 获取数据,如果数据不为空就能获取到该数据,如果为空则根据你传入的参数来创建异常抛出
try {
authorOptional.orElseThrow((Supplier<Throwable>) () -> new RuntimeException("author为空。"));
} catch (Throwable throwable) {
throwable.printStackTrace();
}
4.2.5 过滤
我们可以使用filter方法对数据进行过滤,如果原本是有数据的,但是不符合判断,也会变成一个无数据的Optional对象。
Optional<Author> authorOptional = getAuthorOptional();
authorOptional.filter(author -> author.getAge() > 100)
.ifPresent(author -> System.out.println(author.getName()));
4.2.6 判断
我们可以使用isPresent方法进行是否存在数据的判断。如果为空返回值为false。不为空返回true。
更推荐使用ifPresent方法
Optional<Author> authorOptional = getAuthorOptional();
authorOptional.filter(author -> author.getAge() > 100)
.ifPresent(author -> System.out.println(author.getName()));
4.2.7 数据转换
optional还提供了map可以让我们对数据进行转换,并且转换得到的数据还是被Optional包装好的,保证了我们的使用安全。
更推荐使用ifPresent方法
// 例如:获取作家的书籍集合
Optional<Author> authorOptional = getAuthorOptional();
Optional<List<Book>> optionalBooks = authorOptional.map(author -> author.getBooks());
optionalBooks.ifPresent(books -> books.forEach(book -> System.out.println(book)));
欢迎一起来学习和指导,谢谢关注!
本文来自博客园,作者:xiexie0812,转载请注明原文链接:https://www.cnblogs.com/mask-xiexie/p/16075723.html