JAVA8中Optional 使用详解
前言:
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包装的不会抛出异常。
推荐阅读
-
详解PHP中的mb_detect_encoding函数使用方法
-
详解Django中的ifequal和ifnotequal标签使用
-
java8中使用java.util.Base64报“java.lang.IllegalArgumentException: Illegal base64 character d”
-
php中strtotime时间函数使用详解
-
Lua中break语句的使用方法详解
-
Golang中如何使用lua进行扩展详解
-
详解Linux系统中wget的使用方法
-
PHP中设置、使用、删除Cookie详解
-
php中const与define的使用区别 详解_PHP教程
-
实例详解MySQL中触发器的使用方法