Optional类
java 9 对日期和时间Api进行改进,已经文档化和可执行方式的模块化
我想每个java开发人员,都会遇到这个异常,NullPointerException 空指针异常;如果没有遇到的请举手,有时候修复Null的代价是很高的。
如:建设有个汽车和汽车保险的客户,可以用户,商品,订单等其他模型
person / car / insurance的数据模型
建立模型
public class Person {
private Car car;
public Car getCar(){
return car;
}
}
public class Car{
private Insurance insurance;
public Insurance getInsurance(){
return insurance;
}
}
public class Insurance{
private String name;
public String getName(){return name;}
}
首先可以看出定义的是Person persion / Insurance insurance / String name 定义的时候,全部是定义的null,如果直接调用
getXXXX方法 (getPerson,getInsurance,getName)3个方法,会返回常见的null引用。
采用防御是检测减少NullPointerException,通过判断person ==null 或者是name==null 或者是 Insurance ==null
public String getCarInsuranceName(Person person)
{
if (person!=null){
Car car =person.getCar();
if (car!=null){
Insurance in = car.getInsurance();
if (in !=null){
return in.getName();
}
}
}
return "unknown";
}
上面这种方式每次引入一个变量都需要判断一下null检测,如果引用链上的任何一个遍历的解遍历为null,它就返回unknown,唯一例外的是保险公司的名称,不需要检测,因为必定会有名称。上述代码会有一个很大的问题,就是每次都要不断的重复进行检测null,如果增加一个新的属性,又要嵌套一层if语句,代码不容易扩展。或者我们可以不用嵌套if判断,用if 语句平行判断呢?
public String getCarInsureanceName(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();
}
第二种虽然避免了第一种的if的嵌套的,但每次碰到null 都返回unknow。如果有方法调用这个类,返回unkown 都不知道是哪个类为空,不利于维护异常。
其他语言的null的替代品Groovy
def carInsuranceName = person?.car?.insurance?.name
这段代码非常清晰,person对象可能没有car对象。Croovy的安全导航操作符避免了null引用空指针异常。
引入Optional
可以这样使用Optional
使用了Optional定义的Car类和使用了Optional的Insurancel类
Optional有个empty()返回
在java8 里面可以把在java7的代码改写一下使用Optional类
public class Person {
private Optional car;
public Optional getCar(){
return car;
}
}
public class Car{
private Optional insurance;
public Optional getInsurance(){
return insurance;
}
}
public class Insurance{
private String name;
public String getName(){return name;}
}
分别定义了2个Optional的数据模型Car和Insurance。
使用Optional类的意图并不是消除每个的null引用。它的目的是帮助我们更好的设计出普适的API