java8中的Optional用法浅析

简介

java8中新引入了optional特性,官方说法是更优雅的处理空指针异常,用来表示一个变量的值可以为空也可以不为空,此处引用java 8实战里面的描述:

在你的代码中始终如一地使用Optional,能非常清晰地界定出变量值的缺失是结构上的问
题,还是你算法上的缺陷,抑或是你数据中的问题。另外,我们还想特别强调,引入Optional
类的意图并非要消除每一个null引用。与此相反,它的目标是帮助你更好地设计出普适的API,
让程序员看到方法签名,就能了解它是否接受一个Optional的值。这种强制会让你更积极地将
变量从Optional中解包出来,直面缺失的变量值

所以,optional的作用是显示的表达变量的状态,而不是为了完全消灭NPE。

Option之前

talk is cheap,show me the code:

//根据客户信息获取车辆保险公司的名称
public String getCarInsuranceName(Person person) { 
//对客户判空
 if (person == null) { 
 return "Unknown"; 
 } 
 //对车辆判空
 Car car = person.getCar(); 
 if (car == null) { 
 return "Unknown"; 
 } 
 //对保险公司判空
 Insurance insurance = car.getInsurance(); 
 if (insurance == null) { 
 return "Unknown"; 
 } 
 return insurance.getName(); 
} 

以上代码,可能是我日常开发经常遇到的,过多的NullPointerException检查,影响到了代码的可读性以及优雅性,而且存在潜在的风险,假设其中某个环节未做空指针的检查,则会看到我们熟悉而又讨厌的NullPointerException;

Option特性

创建Optional对象
  1. 声明一个空的Optional对象

Optional<Car> optCar = Optional.empty(); 

  1. 依据一个非空值创建Optional
Optional<Car> optCar = Optional.of(car); 

Optional.of为静态工厂方法,参数为非控制,如果为空,则会直接抛出个NullPointerException

  1. 可接受null的Optional
Optional<Car> optCar = Optional.ofNullable(car);

Optional.ofNullable同样为静态方法,只是参与可为空,如上代码,如果car为null,则会直接返回一个空的Optional对象

Optional对象相关操作方法
get()

Optional对象调用该方法,可以直接获取内容,但是前提是,Optional对象不能为空,否则会抛出NoSuchElementException异常;所以这种方法只有在确定Optional对象非空的情况下调用才是安全的。其实我们只需判断Optional是有值即可,这里官方的api也提供了相关方法,isPresent()返回布尔值来表明Optional对象是否为空

Optional<String> optional= Optional.of("test");
if (optional.isPresent()){ 
  String value = optional1.get();//test
}
orElse(T other)

它允许你在Optional对象不包含值时提供一个默认值,如下:

String nullName = null;
String name=Optional.ofNullable(nullName).orElse("otherName");
  1. orElseGet(Supplier<? extends T> other)
    orElseGet是orElse的延伸版,supplier方法只有在optional对象为空的时候才会执行
String name = Optional.ofNullable(nullName).orElseGet(() -> "otherName");
ifPresent(Consumer<? super T>)

顾名思义,就是当Optional值存在的时候,执行consume函数方法

Optional<String> optional = Optional.of("test");

optional.ifPresent(s -> System.out.println(s));
orElseThrow(Supplier<? extends X> exceptionSupplier)

当Optional值不存的时候,我们也可以抛出异常,异常可以自定义

其他

Optional对象也可以使用java8中的steam闲逛的方法,比如map、flatMap、filter这三种函数,引用java8实战中的样例,如下:
找出年龄大于或者等于minAge参数的Person所对应的保险公司列表。

public String getCarInsuranceName(Optional<Person> person, int minAge) { 
 return person.filter(p -> p.getAge() >= minAge) 
 .flatMap(Person::getCar) 
 .flatMap(Car::getInsurance) 
 .map(Insurance::getName) 
 .orElse("Unknown"); 
} 

注:当Optional对象为空时,则后面的map、flatMap、filter都不会继续执行

Optional实践

用于封装可能为null的值
Object value = map.get("key");

此时,map.get(“key”)可能为空,这里可用使用Optional进行良好的封装处理,如下:

Optional<Object> value = Optional.ofNullable(map.get("key"));

这样一来,只要看到这段代码,后面的人就知道该处的value值可能为空,很好的传达了程序处理的合理性,如果像上面那样,可能直接被当成存在对象使用,而引发空指针异常。

尽量不用于域模型中的某些类型

Optional的设计者并没有考虑将其作为类的字段使用,所以并没有实现Serializable接口,当使用到关于序列化的相关需求时,可能会引发的程序错误。如果确实有需求,可以采用以下方法作为替代方案:

public class Person { 
 private Car car; 
 public Optional<Car> getCarAsOptional() { 
 	return Optional.ofNullable(car); 
 } 
} 

总结

Optional主要是通过类型系统让你的域模型中隐藏的知识显式地体现在你的代码中,换句话说,你永远都不应该忘记语言的首要功能就是沟通,即使对程序设计语言而言也没有什么不同。声明方法接受一个Optional参数,或者将结果作为Optional类型返回,让你的同事或者未来你方法的使用者,很清楚地知道它可以接受空值,或者它可能返回一个空值。

参考:
java 8 in Action
Java8 Optional用法和最佳实践

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值