java 替换null_【Java8】用Option代替Null

javascript权wei指南+高ji入门

298.6元

(需用券)

去购买 >

1cd721f73deb28c005802cb75c0b2386.png

可怕的 NullPointerException

NPE : NullPointerException

空指针异常是最常见的Java异常之一,抛出NPE错误不是用户操作的错误,而是开发人员的错误,应该被避免,那么只能在每个方法中加入非空检查,阅读性和维护性都比较差。

以下是一个常见的嵌套对象:一个用户所拥有的汽车,以及为这个汽车配备的保险。

public class User {

private String userName;

private Car car;

public String getUserName() {

return userName;

}

public void setUserName(String userName) {

this.userName = userName;

}

public Car getCar() {

return car;

}

public void setCar(Car car) {

this.car = car;

}

}

public class Car {

private String carName;

private Insurance insurance;

public String getCarName() {

return carName;

}

public void setCarName(String carName) {

this.carName = carName;

}

public Insurance getInsurance() {

return insurance;

}

public void setInsurance(Insurance insurance) {

this.insurance = insurance;

}

}

public class Insurance {

private String insuranceName;

public String getInsuranceName() {

return insuranceName;

}

public void setInsuranceName(String insuranceName) {

this.insuranceName = insuranceName;

}

}

如果我们此时,需要获取一个用户对应的汽车保险名称,我们可能会写出来以下的代码

private String getInsuranceName(User user) {

return user.getCar().getInsurance().getInsuranceName();

}

显然上面的程序是存在诸多NullPointerException隐患的,为了保证程序的健壮性,我们需要尽量避免出现空指针NullPointerException,那么通常我们会有以下两种写法。

深层质疑

private String getInsuranceName(User user) {

if (user != null) {

Car car = user.getCar();

if (car != null) {

Insurance insurance = car.getInsurance();

if (insurance != null) {

return insurance.getInsuranceName();

}

}

}

return "not found";

}

及时退出

private String getInsuranceName(User user) {

if (user == null) {

return "not found";

}

Car car = user.getCar();

if (car == null) {

return "not found";

}

Insurance insurance = car.getInsurance();

if (insurance == null) {

return "not found";

}

return insurance.getInsuranceName();

}

为了避免出现空指针,我们通常会采用以上两种写法,但是它们复杂又冗余,为了鼓励程序员写更干净的代码,代码设计变得更加的优雅。JAVA8提供了Optional类来优化这种写法。

Option入门

Java 8中引入了一个新的类java.util.Optional。这是一个封装Optional值的类。举例来说,使用新的类意味着,如果你知道一个人可能有也可能没有车,那么Person类内部的car变量就不应该声明为Car, 遇某人没有车时把null引用值给它,而是应该如下图所示直接将其声明为Optional类型。

bVbyznw?w=934&h=468

变量存在时,Optional类只是对类简单封装。变量不存在时,缺失的值会被建模成一个“空” 的Optional对象,由方法Optional.empty()返回。它返回Optional类的特定单一实例。

null引用和Optional.empty() 有什么本质的区别吗?

从语义上,你可以把它们当作一回事儿,但是实际中它们之间的差别非常大:如果你尝试直接引用一个null,一定会触发NullPointerException,不过使用 Optional.empty()就完全没事儿,它是Optional类的一个有效对象。

使用Optional而不是null的一个非常重要而又实际的语义区别是,第一个例子中,我们在声明变量时使用的是Optional类型,而不是Car类型,这句声明非常清楚地表明了这里发生变量缺失是允许的。与此相反,使用Car这样的类型,可能将变量赋值为null,你只能依赖你对业务模型的理解,判断一个null是否属于该变量的有效值又或是异常情况。

public class User {

private String userName;

private Optional car;

public String getUserName() {

return userName;

}

public Optional getCar() {

return car;

}

}

public class Car {

private String carName;

private Optional insurance;

public String getCarName() {

return carName;

}

public Optional getInsurance() {

return insurance;

}

}

public class Insurance {

private String insuranceName;

public String getInsuranceName() {

return insuranceName;

}

}

发现Optional是如何 富你模型的语义了吧。代码中person引用的是Optional, 而car引用的是Optional,这种方式非常清晰地表达了你的模型中一个person 可能有也可能没有car的情形,同样,car可能进行了保险,也可能没有保险。

与此同时,我们看到insurance的名称insuranceName被声明成String类型,而不是Optional- ,这非常清楚地表明声明为insurance的类中的名称字段insuranceName是必须存在的。

使用这种方式, 一旦通过引用insurance获取insuranceName时发生NullPointerException,你就能非常确定地知道出错的原因,不再需要为其添加null的检查查,因为null的检查查只会掩盖问题,并未真正地修复问题。

insurance必须有个名字,所以,如果你遇到一个insurance没有名称,你需要调查你的数据出了什么问题,而不应该再添加一段代码,将这个问题隐藏。

原文链接:https://segmentfault.com/a/1190000020593181

java 11官方入门(第8版)教材

79.84元

包邮

(需用券)

去购买 >

f0f3f55624fb396b1764d42d6df88864.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值