1.Optional概念
java.util.Optional<T>
类是一个封装了Optional
值的容器对象,Optional
值可以为null
,如果值存在,调用isPresent()
方法返回true
,调用get()
方法可以获取值。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有用的方法,这样我们就不用显式进行空值检测。
Optional 类的引入很好的解决空指针异常。
以下是 java.util.Optional<T> 类的声明:
public final class Optional<T> extends Object
2.为什么要使用Optional
目的:避免使用null
检查
作为Java开发人员,几乎所有人都遇到过NullPointerException
异常,大多数人遇到NullPointerException
异常时都会在异常出现的地方加上if
代码块来判断值不为空,比如下面的代码:
public void bindUserToRole(User user) { if (user == null) { return; } String roleId = user.getRoleId(); if (roleId == null) { return; } Role = roleDao.findOne(roleId); if (role != null) { role.setUserId(user.getUserId()); roleDao.save(role); } }
方法内有三个不同的返回点,出错后调试也不容易,你都不知道是那个值导致了NullPointerException
异常。
基于上面的原因,Java 8中引入了一个新的类Optional
,用以避免使用null
值引发的种种问题。
3.创建Optional
对象
Optional
类提供类三个方法用于实例化一个Optional
对象,它们分别为empty()
、of()
、ofNullable()
,这三个方法都是静态方法,可以直接调用。
(1)empty()
方法
empty()
方法用于创建一个没有值的Optional
对象:
Optional<String> emptyOpt = Optional.empty();
empty()
方法创建的对象没有值,如果对emptyOpt
变量调用isPresent()
方法会返回false
,调用get()
方法抛出NullPointerException
异常。
(2)of()
方法
of()
方法使用一个非空的值创建Optional
对象:
String str = "Hello World";
Optional<String> notNullOpt = Optional.of(str);
(3)ofNullable()
方法
ofNullable()
方法接收一个可以为null
的值:
Optional<String> nullableOpt = Optional.ofNullable(str);
如果str
的值为null
,得到的nullableOpt
是一个没有值的Optional
对象。
若是集合类型:
Optional<List<Student>> studentList1 = Optional.ofNullable(studentList);
(4)of()
和ofNullable()
方法辨析
当你很确定一个对象不可能为null
的时候,应该使用of()
方法,否则,尽可能使用ofNullable()
方法,比如:
public static void method(Role role) { // 当Optional的值通过常量获得或者通过关键字new初始化,可以直接使用of()方法 Optional<String> strOpt = Optional.of("Hello World"); Optional<User> userOpt = Optional.of(new User()); // 方法参数中role值不确定是否为null,使用ofNullable()方法创建 Optional<Role> roleOpt = Optional.ofNullable(role); }
4.提取Optional
对象中的值
如果我们要获取User
对象中的roleId
属性值,常见的方式是直接获取:
String roleId = null; if (user != null) { roleId = user.getRoleId(); }
使用Optional
中提供的map()
方法可以以更简单的方式实现:
Optional<User> userOpt = Optional.ofNullable(user);
Optional<String> roleIdOpt = userOpt.map(User::getRoleId);
map()
方法与Stream API中的map()
一样,类似于映射操作,将原始类型映射为一个新的类型。
5.使用orElse()
方法获取值
源码:
public T orElse(T var1) { return this.value != null ? this.value : var1; }
orElse()
:如果有值就返回T,否则返回一个给定的值作为默认值;
案例1:
return str != null ? str : "Hello World"
上面的代码表示判断字符串str
是否为空,不为空就返回,否则,返回一个常量。使用Optional
类可以表示为:
return strOpt.orElse("Hello World")
案例2:
public class OptionalTest { public static void main(String[] args) { List<Student> studentList=new ArrayList<>(); Student student1=new Student(); student1.setAge(10); student1.setName("lucky"); Student student2=new Student(); student2.setAge(12); student2.setName("linda"); studentList.add(student1); studentList.add(student2); Optional<List<Student>> studentList1 = Optional.ofNullable(studentList); List<Student> studentList2 = Optional.ofNullable(studentList).orElse(new ArrayList<>()); List<Integer> collect = Optional.ofNullable(studentList).orElse(new ArrayList<>()).stream().map(Student::getAge).collect(Collectors.toList()); System.out.println("hello"); } }
debug截图:
参考文献:https://lw900925.github.io/java/java8-optional.html