之前的博客介绍了Optional的简单使用,但经过一段时间的学习理解,发现其实Optional的用法实际上就是它本身的含义,即可能为空,避免了在获取字段属性时做过多的null判断。具体如下
public class Man{
private String name;
private Optional<Son> son;
//此处省略name的get和set方法
public void setSon(Son son){
this.son = Optional.ofNullable(son);
}
public Optional<Son> getSon(){
return son;
}
}
public class Son{
private String name;
//此处省略name的get和set方法
}
比如在上述情况中,一个男子不一定有儿子,那么获取儿子名返回为null即可,son本身为空不影响业务本身。那按照以前的情况获取儿子名,则如下:
public String getSonName(Man man){
Son son = man.getSon();
if(son!=null){
return son.getName();
}
return null;
}
但是如果按照前面的设计,则如下:
public String getSonName(Man man){
return man.getSon().map(Son::getName).orElse(null);
}
可能乍一看觉得差不多,但是请别忽略一点,如果类的层次比较多的话,比如如果Son之下还有其他类,那么获取最终的类中的字段的时候,那么就可以少了很多为空判断了,这主要归功于map方法,具体map方法的介绍看我上一篇。还有一点,那么就是如果需要抛异常,如果其中某个字段为空,那么抛个统一异常(即如果最终要获取的字段为null,是影响业务需求的),如下
public String getSonName(Man man){
//其中NullPointerException可以换成自定义的其他异常等
return man.getSon().map(Son::getName).orElseThrow(()->new NullPointerException("子字段属性不能为空"));
}
但是上述面临一个问题即Optional无法被序列化,因此如果需要在序列化的类中使用,那么可以这样子设计
public class Man{
private String name;
private Son son;
//此处省略name的get和set方法
public void setSon(Son son){
this.son = son;
}
//即字段属性照常设置,获取时说明可能为空。
public Optional<Son> getSon(){
return Optional.ofNullable(this.son);
}
}