如何处理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实战 第十章

java8 用Optional取代null的更多相关文章

  1. 用optional取代null

    Java8引入了java.util.Optional<T>,它是一个封装的Optional值的类.变量存在时,Optional类只是对类简单封装.变量不存在时,缺失的值会被建模成一个空的O ...

  2. 《Java 8 in Action》Chapter 10:用Optional取代null

    1965年,英国一位名为Tony Hoare的计算机科学家在设计ALGOL W语言时提出了null引用的想法.ALGOL W是第一批在堆上分配记录的类型语言之一.Hoare选择null引用这种方式,& ...

  3. Java 8 (9) Optional取代null

    NullPointerException,大家应该都见过.这是Tony Hoare在设计ALGOL W语言时提出的null引用的想法,他的设计初衷是想通过编译器的自动检测机制,确保所有使用引用的地方都 ...

  4. Java8之Optional类

    写在前头 今天再看阿里的Java开发手册,里面异常处理第10条提到这样一个建议. [推荐]防止 NPE ,是程序员的基本修养,注意 NPE 产生的场景:1 ) 返回类型为基本数据类型,return 包 ...

  5. Java8的Optional:如何干掉空指针?

    目录 Optional概述 Optional简单案例 Optional的主要方法 参考阅读 Optional概述 Optional 是个容器:它可以保存类型T的value,或者仅仅保存null.Opt ...

  6. JDK8新特性:使用Optional避免null导致的NullPointerException

    空指针异常是导致Java应用程序失败的最常见原因.以前,为了解决空指针异常,Google公司著名的Guava项目引入了Optional类,Guava通过使用检查空值的方式来防止代码污染,它鼓励程序员写 ...

  7. Java8:使用 Optional 处理 null

    写过 Java 程序的同学,一般都遇到过 NullPointerException :) —— 为了不抛出这个异常,我们便会写如下的代码: User user = getUserById(id); i ...

  8. Java8之使用Optional进行Null处理

    Optional类这是Java 8新增的一个类,用以解决程序中常见的NullPointerException异常问题,本篇文章将详细介绍Optional类,以及如何用它消除代码中的null检查. 1. ...

  9. java8中optional和.stream().map()

    使用optional的好处:是一个可以包含或不可以包含非空值的容器对象,更加友好的处理程序中的空对象. Optional<T>有方法 isPresent() 和 get() 是用来检查其包 ...

随机推荐

  1. Chrome浏览器内部协议Chrome://收集

    Chromium 采用 Chrome:// 协议开头的形式, 规定了一系列的内部协议, 有的用来显示数据, 有的用来实现一些功能, 但对普通用户进行了屏蔽.在Chrome浏览器地址栏直接访问就好了! ...

  2. linux系统中如何查看最后一封mail

    1. mail命令查看邮件列表 2.file 命令查看一共多少封邮件 3.直接键入278 查看最后一封邮件内容 4. 输入q 从邮件阅读模式退出

  3. javascript中 typeof和instanceof的区别

    <一> js中typeof的用法进行了详细的汇总介绍 (1)返回一个变量的基本类型 回顾基本类型(number,string,boolean,null,undefined,object) ...

  4. 逆向破解之160个CrackMe —— 008-009

    CrackMe —— 008 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...

  5. selenium中的等待方法及区别

    等待是为了使脚本执行更加稳定 常用的休眠方式: 1.time模块的sleep方法 :引入from time import sleep 2.implicitly_wait():设置webdriver等待 ...

  6. Celery(异步任务,定时任务,周期任务)

    1.什么是Celery Celery是基于Python实现的模块,用于异步.定时.周期任务的. 组成结构: 1.用户任务 app 2.管道broker 用于存储任务 官方推荐 redis/rabbit ...

  7. lca:异象石(set+dfs序)

    题目:https://loj.ac/problem/10132 #include<bits/stdc++.h> using namespace std; ,N,k=,head[]; str ...

  8. Mybatis容易遇到的问题

    1.MyBatis中#和$的区别? 1.使用#的原理是?占位符,而$的原理为直接字符串拼接方式 2.$方式一般使用在写数据库中的固定字段时候才会使用例如表名或者列名(select * from use ...

  9. python字符的表示格式

    %% 百分号标记 #就是输出一个% %c 字符及其ASCII码%s 字符串%d 有符号整数(十进制)%u 无符号整数(十进制)%o 无符号整数(八进制)%x 无符号整数(十六进制)%X 无符号整数(十 ...

  10. django-发送文件

    客户端授权密码”,勾选“开启”,弹出新窗口填写手机验证码. settings.py配置 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBac ...