Null 带来的问题:
- 它是错误之源
NullPointerException是目前java程序开发中最典型的异常 - 它会使代码膨胀
它让你的代码充斥着深度嵌套的null检查,代码的可读性差 - 它自身没有任何的语义
尤其是,它代表了在静态类型语言中一种错误的方式对缺失的变量值的建模Optional类
java8中引人了一个新的类java.util.Optional< T >。
代码示例 1:1234567891011121314public class Person{private Optional < Car > car;public Optional< Car> getCar(){return car;}}public class Car{private Optional< Insurance> insurance;public Optional< Insurance> getInsurance(){return insurance;}}pubic class Insurance{private String name;pulic String getName(){return name;}}
当变量存在的时候,Optional类只是对类的简单封装。变量不存在的时候,缺失的值会被建模成为一个”空”的Optional对象,该对象可以由方法Optional.empty()返回,同时解引用这个Optional类的有效的”空”对象是完全不会出事的。
上述的代码示例中:
- Person类表示某个人(实例)可能有车,也可能没车,因此将这个字段声明为Optional,表明Person是允许缺失的,通过Optional为缺失null安全建模;
- Car类表示某台车可能买了保险,也有可能没有买保险;
- Insurance类中,每个保险是肯定有名字的,所以无须声明为Optional;
使用Optional
创建一个Optional对象
声明一个空的Optional:通过静态工厂方法Optional.empty(),创建一个空的Optional对象;
OptionaloptCar = Optional.empty();
或者,使用静态工厂方法Optional.ofNullable,创建一个允许null值得Optional对象
OptionaloptCar = Optional.ofNullable(car); - 利用map,flatmap从Optional对象中提取值
参考java8中java.util.Optional函数Api可以得知map,flatmap的用法以及区别。借助上述的代码示例1,比较map方法与flatmap方法的用法。Optional<Insurance> optInsurance = Optional.ofNullable(insurance);
Optional<String> name = optInsurance.map(Insurance :: getName);
这里的map用方法和流中的map用法几乎一致,map操作会将提供的函数应用于流的每个元素,这里我们将Optional对象看作一种特殊的集合,至少包含一个元素。如果Optional包含一个值,那函数就将改值作为参数传递给map,最后对将得到的值用Optional类包装。如果Optional为空,那就什么都不做。
但是注意以下代码:
Optional<Person> optPerson = Optional.of(person);
这里optPerson是Optional类型的变量,调用map方法没有问题,但是其中包含的Person.getCar返回的是一个Optional 类型的对象,导致 optPerson.map(Person :: getCar);
的结果是返回一个Optional>类型的变量。这个时候我们需要用到flatmap方法,可以将多层Optional包裹的值合并为一个Optional返回函数结果。
注意:Optional类并没有实现Serializable接口