如何处理null

怎样做才能避免不期而至的NullPointerException呢?通常,可以在需要的地方添加null的检查(过于激进的防御式检查甚至会在不太需要的地方添加检测代码),并且添加的方式往往各有不同。

null-安全的第一种尝试:深层质疑

“深层质疑”,原因是它不断重复着一种模式:每次不确定一个变量是否为null时,都需要添加一个进一步嵌套的if块,也增加了代码缩进的层数。很明显,这种方式不具备扩展性,同时还牺牲了代码的可读性。

null-安全的第二种尝试:过多的退出语句

第二种尝试中,试图避免深层递归的if语句块,采用了一种不同的策略:每次遭遇null变量,都返回一个字符串常量“Unknown”。然而,这种方案远非理想,现在这个方法有了四个截然不同的退出点,使得代码的维护异常艰难。

使用Optional获取car的Insurance名称

汲取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的结果值为空,设置默认值
}

创建Optional对象

1. 声明一个空的Optional

可以通过静态工厂方法Optional.empty,创建一个空的Optional对象:

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

2. 依据一个非空值创建Optional

还可以使用静态工厂方法Optional.of,依据一个非空值创建一个Optional对象:

如果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实战 第十章

最新文章

  1. Android实现页面跳转及传递参数的方法
  2. Play Framework 完整实现一个APP(二)
  3. 了解Json
  4. 《QT Creator快速入门》
  5. Java I/O 文件加锁,压缩
  6. 安装 Visual Stuidio 2010 失败
  7. iOS开发——设备篇&amp;ios8文件路径
  8. springMVC+MyBatis+Spring 整合(4) ---解决Spring MVC 对AOP不起作用的问题
  9. 函数 stat() 详解
  10. java 中的 &amp; | ~ ^ 运算符分析
  11. Json帮助类以及如何使用
  12. JavaScript 之 Cookie
  13. lua中获取时间
  14. Javascript一道面试题
  15. 【iOS】OC-AFNetworking 2.0 跟踪文件上传进度
  16. Moving or disabling the package cache for Visual Studio 2017
  17. CentOS7 下编译 Hadoop
  18. ProtoBuf3 C++使用篇
  19. django扩展User认证系统
  20. Ubuntu忘记MySQL密码重设方法

热门文章

  1. subprocess模块的使用注意
  2. CSS制作华为mate8手机模型示例
  3. Redis.Memcache和MongoDB区别?
  4. Tensorflow可视化-P295-Tensorboard可视化
  5. Python 09 安装torch、torchvision
  6. Cogs 1632. 搬运工(二分图最小点覆盖)
  7. Python 元类使用讲解
  8. GoCN每日新闻(2019-09-30)
  9. 最近公司遇到了APR攻击,顺便了解一下知识
  10. Java后台读取excel表格返回至Web前端