简介
从 Java 8 引入的一个很有趣的特性是 Optional 类。Optional 类主要解决的问题是臭名昭著的空指针异常(NullPointerException) —— 每个 Java 程序员都非常了解的异常。本质上,这是一个包含有可选值的包装类,这意味着 Optional 类既可以含有对象也可以为空。
例子
传统方法处理空指针
String isocode = user.getAddress().getCountry().getIsocode().toUpperCase();
那么就需要用if-else语句
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改进
Optional.ofNullable(user)
.map(User::getAddress)
.map(Address::getCountry)
.map(Country::getIsocode)
.map(String::toUpperCase)
.ifPresent(isocode -> {
// 处理非空的 isocode
System.out.println("Updated isocode: " + isocode);
});
这里的每个 map 方法都会对 Optional 中的值进行映射操作,如果某个阶段的值为 null,则整个表达式会在该处终止,不再往下执行。最后的 ifPresent 方法用于处理映射后的非空值。
常见使用方法
创建Optional对象
- 创建一个空的Optional实例
Optional<String> emptyOptional = Optional.empty()
- 创建一个Optional实例,且不能为空,否则会抛出异常
Optional<String> strOpt = Optional.of("Cannot be null")
- 创建一个Optional实例,可以为空,也可以不为空
Optional<String> nullOrExist = Optional.ofNullable("aaa");
Optional<String> nullOrExist = Optional.ofNullable(null);
获取Optional对象中的值
直接使用get
方法
Optional<String> strOpt = Optional.of("Cannot be null")
String myStr = strOpt.get()
如果为空,则指定一个生成器,可用于返回默认值
Optional<String> strOpt = Optional.ofNullable(null)
String myStr = strOpt.orElseGet(() -> "this is a string if null")
如果为空抛出异常
Optional<String> strOpt = Optional.ofNullable(null)
String myStr = strOpt.orElseThrow(RuntimeException::new)
判断是否包含对象
使用isPresent
Optional<String> strOpt = Optional.ofNullable(null)
if (strOpt.isPresent()) {
System.out.println("exist")
}
使用ifPresent
,并给出存在后执行的内容
Optional<String> myStr = Optional.of("this is a string");
myStr.ifPresent(str -> System.out.println("das" + 2));
过滤转换
使用filter
,注意,如果条件满足filter会返回一个Optional对象,不满足则会返回一个空的Optional对象,因此可以链式调用,也可以在末尾加上ifPresent
,orElse
等等
Optional<Apple> appleCanBeNull = Optional.ofNullable(new Apple(125.5F, Color.RED));
Optional<Apple> apple = appleCanBeNull.filter(a -> a.getWeight() > 150)
.filter(a -> Color.RED.equals(a.getColor()));;
if (apple.isPresent()) {
System.out.println("apple greater than 100 exists");
}
使用map
进行值的转换,可用于获取对象的具体属性,例如获取苹果的重量
Float appleWeight = appleCanBeNull.map(Apple::getWeight).orElse(0.0F);
使用flatMap
获取一个被Optional包装的对象的具体属性
Optional<Float> weight = appleCanBeNull.flatMap(apple -> Optional.ofNullable(apple.getWeight()));