怎样作才能避免不期而至的NullPointerException呢?一般,能够在须要的地方添加null的检查(过于激进的防护式检查甚至会在不太须要的地方添加检测代码),而且添加的方式每每各有不一样。java
“深层质疑”,缘由是它不断重复着一种模式:每次不肯定一个变量是否为null时,都须要添加一个进一步嵌套的if块,也增长了代码缩进的层数。很明显,这种方式不具有扩展性,同时还牺牲了代码的可读性。安全
第二种尝试中,试图避免深层递归的if语句块,采用了一种不一样的策略:每次遭遇null变量,都返回一个字符串常量“Unknown”。然而,这种方案远非理想,如今这个方法有了四个大相径庭的退出点,使得代码的维护异常艰难。spa
汲取Haskell和Scala的灵感,Java 8中引入了一个新的类java.util.Optional<T>。这是一个封装Optional值的类。设计
public String getCarInsuranceName(Optional<Person> person){ return person.flatMap(Person::getCar) .flatMap(Car::getInsurance) .map(Insurance::getName) .orElse("Unknown");//若是Optional的结果值为空,设置默认值 }
1. 声明一个空的Optional指针
能够经过静态工厂方法Optional.empty,建立一个空的Optional对象:code
Optional<Car> optCar = Optional.empty();
2. 依据一个非空值建立Optional对象
还可使用静态工厂方法Optional.of,依据一个非空值建立一个Optional对象:blog
若是car是一个null,这段代码会当即抛出一个NullPointerException,而不是等到试图访问car的属性值时才返回一个错误。递归
Optional<Car> optCar = Optional.of(car);
3. 可接受null的Optiona字符串
使用静态工厂方法Optional.ofNullable,能够建立一个容许null值的Optional对象:
若是car是null,那么获得的Optional对象就是个空对象。
Optional<Car> optCar = Optional.ofNullable(car);
Optional类的方法
•null引用在历史上被引入到程序设计语言中,目的是为了表示变量值的缺失。
•Java 8中引入了一个新的类java.util.Optional<T>,对存在或缺失的变量值进行建模。
•可使用静态工厂方法Optional.empty、Optional.of以及Optional.ofNullable建立Optional对象。
•Optional类支持多种方法,好比map、flatMap、filter,它们在概念上与Stream类中对应的方法十分类似。
•使用Optional会迫使更积极地解引用Optional对象,以应对变量值缺失的问题,最终,能更有效地防止代码中出现不期而至的空指针异常。
•使用Optional能帮助设计更好的API,用户只须要阅读方法签名,就能了解该方法是否接受一个Optional类型的值。
附:类代码
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; } }
附:使用Optional从新定义Person/Car/Insurance的数据模型
public class Person { private Optional<Car> car;//人可能有车,也可能没有车,所以将这个字段声明为Optional public Optional<Car> getCar() { return car; } } public class Car { private Optional<Insurance> insurance;//车可能进行了保险,也可能没有保险,因此将这个字段声明为Optional public Optional<Insurance> getInsurance() { return insurance; } } public class Insurance { private String name;//保险公司必须有名字 public String getName() { return name; } }
文章来源:java8实战 第十章