JAVA8中Optional 使用详解

it2023-01-24  50

前言:

1965年,英国一位名为Tony Hoare的计算机科学家在设计ALGOL W语言时提出了null引用 的想法。ALGOL W是第一批在堆上分配记录的类型语言之一。Hoare选择null引用这种方式,“只 是因为这种方法实现起来非常容易”。虽然他的设计初衷就是要“通过编译器的自动检测机制, 确保所有使用引用的地方都是绝对安全的”,他还是决定为null引用开个绿灯,因为他认为这是 为“不存在的值”建模最容易的方式。很多年后,他开始为自己曾经做过这样的决定而后悔不迭, 把它称为“我价值百万的重大失误”。我们已经看到它带来的后果——程序员对对象的字段进行 检查,判断它的值是否为期望的格式,最终却发现我们查看的并不是一个对象,而是一个空指针, 它会立即抛出一个让人厌烦的NullPointerException异常。

这是JAVA8实战中对JAVA语言中null的一段叙述,NullPointerException 异常在实际开发中会遇到很多,对于我们写代码来说也很麻烦,一般会看到,都是if else if 去处理这些,当前来看问题好像是解决了,对于后期维护上面来说,其实是一个定时炸弹。

public String getCarInsuranceName(Person person) { return person.getCar().getInsurance().getName(); }

这个例子中就最常见,如果getCar为null,那么在进行下一步get时候就会出NullPointerException异常 先来看看有些避免出现NullPointerException异常的方法呢?

1.采用防御式检查减少 NullPointerException

public String getCarInsuranceName(Person person) { if (person != null) { Car car = person.getCar(); if (car != null) { Insurance insurance = car.getInsurance(); if (insurance != null) { return insurance.getName(); } } } return "Unknown"; }

也就是常见的if else 去层层去判断知道不为null,才放回正确的值

每次你不确定一个变量是否为null时,都需要添加一个进一步嵌套的if块,也增加了代码缩进的层数

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

public String getCarInsuranceName(Person person) { if (person == null) { return "Unknown"; } Car car = person.getCar(); if (car == null) { return "Unknown"; } Insurance insurance = car.getInsurance(); if (insurance == null) { return "Unknown"; } return insurance.getName(); }

使用 return 进行多次判断直到不为null才返回正确的值

每次你遭遇null变量,都返回一个字符串常量“Unknown”。然而,这种方案远非理想,现在这个方法有了四个截然不同的退出点,使得代码的维护异常艰难

在其他语言中也对null进行过一些处理,Groovy 语言中就对null进行过设计

def carInsuranceName = person?.car?.insurance?.name

有点类似三目运算符,关于Java 7的讨论中曾经建议过一个类似的功能,不过后来又被舍弃了

JAVA8 Optional:

使用新的类意味着,如果你知道一个人可能有也可能 没有车,那么Person类内部的car变量就不应该声明为Car,遭遇某人没有车时把null引用赋值给它,而是应该像图10-1那样直接将其声明为Optional类型。

使用 Optional 进行包装一层,在空时并不会直接抛出异常 Optional 创建方式:

声明一个空的Optional Optional optCar = Optional.empty();依据一个非空值创建Optional Optional optCar = Optional.of(car); car为空会抛异常可接受null的Optional Optional optCar = Optional.ofNullable(car); 不会抛异常,是个空对象

看看如果我们根据key获取值,如果这个可以不存在时会发生什么呢?

Map<String,Object> map = new HashMap<>(); Object name = map.get("name"); System.out.println(name); Optional<Object> optional = Optional.ofNullable(map.get("name")); System.out.println(optional);

执行结果: null Optional.empty 没有值,Optional不会直接为null,如果这时候我们进行toString方法时 上面的会抛出异常,而经过Optional包装的不会抛出异常。

最新回复(0)