简述
Optional类是java8中引入的一个非常有用的类,主要用处是解决编程中的空指针异常,本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。Optional 是 Java 实现函数式编程的强劲一步,并且帮助在范式中实现。
空指针异常的麻烦
在java8之前,任何访问对象方法或属性的调用都有可能导致空指针异常,例如:
String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();
这行代码如果我们需要确保不触发异常,我们就要写成:
if (user != null) { Address address = user.getAddress(); if (address != null) { Country country = address.getCountry(); if (country != null) { String isocode = country.getIsocode(); if (isocode != null) { isocode = isocode.toUpperCase(); } } } }
创建Optional实例
使用empty()创建空实例
Optional<User> emptyOpt = Optional.empty();
尝试访问emptyOpt变量的值会导致NoSuchElementException
使用of()或ofNullable()方法创建包含值的Optional,不同之处在于:如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException
Optional<User> opt1 = Optional.of(user);
Optional<User> opt1 = Optional.ofNullable(user);
访问Optional对象的值
使用get()方法获取Optional的值
Optional<User> opt1 = Optional.of(user);
User tmp = opt1.get();
get方法会在值为null的时候抛出异常,我们可以用ifPresent()方法验证值是否为空
返回默认值
orElse()方法可以在创建实例时就指定返回的默认值
User user = null; User user2 = new User("anna@gmail.com", "1234"); User result = Optional.ofNullable(user).orElse(user2);
因为user是空,所以此时我们想获取result的值的话会得到user2
我们也可以使用orElseGet(),如果没有值,它会执行作为参数传入的 Supplier(供应者) 函数式接口,并将返回其执行结果
User result = Optional.ofNullable(user).orElseGet( () -> user2);
不同的是使用orElse的话无论创建的值是否为空,都会orElse里的代码,如果里面有创建新的实例,这会对性能产生很大影响
另外我们可以使用orElseThrow(),它会在对象为空的时候抛出异常,而不是返回备选的值
User result = Optional.ofNullable(user) .orElseThrow( () -> new IllegalArgumentException());
此时如果user为空,会抛出我们定义的异常IllegalArgumentException
转换值
我们可以使用map方法,将 Optional里的元素进行转换
User user = new User("anna@gmail.com", "1234"); String email = Optional.ofNullable(user) .map(u -> u.getEmail()).orElse("default@gmail.com");
注意无论是user为null,还是user里的Email为空,都会触发返回orElse里的默认值,这也就Optional的map操作的链式调用的精髓,我们可以不断的接着写map,无需一次次地判断是否为空
注意如果当对象发生Optinoal嵌套的时候,我们需要使用flatMap方法,详细请看:https://blog.csdn.net/qq_35634181/article/details/101109300
过滤值
filter()接受一个Predicate参数,返回测试结果为 true 的值
用法和stream的filter一模一样,例如我们可以检查用户的邮箱是否带@
User user = new User("anna@gmail.com", "1234"); Optional<User> result = Optional.ofNullable(user) .filter(u -> u.getEmail() != null && u.getEmail().contains("@"));
对原来if的改进
对于User类我们对其进行重构,使其getter方法返回Optional类
public class User { private Address address; public Optional<Address> getAddress() { return Optional.ofNullable(address); } // ... } public class Address { private Country country; public Optional<Country> getCountry() { return Optional.ofNullable(country); } // ... }
上面的嵌套结构可以用下面的图来表示:
之前冗杂的if判断我们就可以改成这样:
String result = Optional.ofNullable(user) .flatMap(u -> u.getAddress()) .flatMap(a -> a.getCountry()) .map(c -> c.getIsocode()) .orElse("default");
也可以简写成这样:
String result = Optional.ofNullable(user)
.flatMap(User::getAddress)
.flatMap(Address::getCountry)
.map(Country::getIsocode)
.orElse("default");
Reference
https://blog.csdn.net/wwe4023/article/details/80760416
https://blog.csdn.net/qq_35634181/article/details/101109300