Java8 新特性 | 如何风骚走位防止空指针异常
文章整理翻译自 https://winterbe.com/posts/2015/03/15/avoid-null-checks-in-java/
文章首发于个人网站: https://www.exception.site/java8/java8-avoid-null-check
要说 Java 编程中哪个异常是你印象最深刻的,那 NullPointerException 空指针可以说是臭名昭著的。不要说初级程序员会碰到,
即使是中级,专家级程序员稍不留神,就会掉入这个坑里。
Null 引用的发明者 Tony Hoare 曾在 2009 年作出道歉声明,声明中表示,到目前为止,空指针异常大约给企业已造成数十亿美元的损失。
下面是 Tony Hoare 的原话:
我将 Null 引用的设计称为是一个数十亿美元的错误。1965 那年,我正在用面向对象语言(ALGOL W) 设计首个功能全面的系统。当时我的考量是,确保所有被使用的引用都是安全的,编译器会自动进行检查。但是,我没有抵住诱惑,加入了 Null 引用,仅仅是为了实现起来省事。这之后,它导致了数不清的 bug、错误和系统崩溃,也为企业导致了不可估量的损失。
事已至此,我们必须学会面对它。So, 我们要如何防止空指针异常呢?
唯一的办法就是对可能为 Null 的对象添加检查。但是 Null 检查是繁琐且痛苦的。所以一些比较新的语言为了处理 Null 检查,特意添加了特殊的语法,如空合并运算符。
不幸的是,在老版本的 Java 中并没有提供这样的语法糖。Java8 中在这方面做了改进。所以,这篇文章就特意来介绍一下如何在 Java8 中利用新特性来编写防止 NullPointerException的发生。
Java8 中如何加强对 Null 对象的检查?
在上篇文章 Java8 新特性指导手册 中简单的提了一下如何通过 Optional 类来对对象做空校验。接下来,我们再细说一下:
在业务系统中,对象中嵌套对象是经常发生的场景,如下示例代码:
// 最外层对象
class Outer {
Nested nested;
Nested getNested() {
return nested;
}
}
// 第二层对象
class Nested {
Inner inner;
Inner getInner() {
return inner;
}
}
// 最底层对象
class Inner {
String foo;
String getFoo() {
return foo;
}
}
业务中,假设我们需要获取 Outer 对象对底层的 Inner 中的 foo 属性,我们必须写一堆的非空校验,来防止发生 NullPointerException:
// 繁琐的代码
Outer outer = new Outer();
if (outer != null && outer.nested != null && outer.nested.inner != null) {
System.out.println(outer.nested.inner.foo);
}
通过 Optional
在 Java8 中,我们有更优雅的解决方式,那就是使用 Optional是说,我们可以在一行代码中,进行流水式的 map 操作。而 map 方法内部会自动进行空校验:
Optional.of(new Outer())
.map(Outer::getNested)
.map(Nested::getInner)
.map(Inner::getFoo
.ifPresent(System.out::println); // 如果不为空,最终输出 foo 的值
通过 suppiler 函数自定义增强 API
上面这种方式个人感觉还是有点啰嗦,我们可以利用 suppiler 函数来出一个终极解决方案:
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
}
catch (NullPointerException e) {
// 可能会抛出空指针异常,直接返回一个空的 Optional 对象
return Optional.empty();
}
}
利用上面的 resolve 方法来重构上述的非空校验代码段:
Outer obj = new Outer();
// 直接调用 resolve 方法,内部做空指针的处理
resolve(() -> obj.getNested().getInner().getFoo());
.ifPresent(System.out::println); // 如果不为空,最终输出 foo 的值
最后
你需要知道的是,上面这两个解决方案并没传统的 null 检查性能那么高效。但在绝大部分业务场景下,舍弃那么一丢丢的性能来方便编码,是完全可取,
除非是那种对性能有严格要求的场景,我们才不建议使用。
个人觉得,真要拿这点性能说事,还不如去优化优化 sql 语句,业务逻辑等。
GitHub 地址
https://github.com/weiwosuoai/java8_guide
Java8 新特性 | 如何风骚走位防止空指针异常的更多相关文章
- Java8新特性之空指针异常的克星Optional类
Java8新特性系列我们已经介绍了Stream.Lambda表达式.DateTime日期时间处理,最后以"NullPointerException" 的克星Optional类的讲解 ...
- 【Java8新特性】Optional类在处理空值判断场景的应用 回避空指针异常 编写健壮的应用程序
一.序言 空值异常是应用运行时常见的异常,传统方式为了编写健壮的应用,常常使用多层嵌套逻辑判断回避空指针异常.Java8新特性之Optional为此类问题提供了优雅的解决方式. 广大程序员朋友对空值异 ...
- java8新特性全面解析
在Java Code Geeks上有大量的关于Java 8 的教程了,像玩转Java 8--lambda与并发,Java 8 Date Time API 教程: LocalDateTime和在Java ...
- 这可能是史上最好的 Java8 新特性 Stream 流教程
本文翻译自 https://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ 作者: @Winterbe 欢迎关注个人微信公众 ...
- 干货 | Java8 新特性教程
本教程翻译整理自 https://github.com/winterbe/java8-tutorial 本教程首发自个人网站: https://www.exception.site/java8/jav ...
- 乐字节-Java8新特性之Optional
上一篇小乐带大家了解了Java新特性之Stream,接下来将会继续述说Java新特性之Optional Optional<T>类(java.util.Optional)是一个容器类,代表一 ...
- java8新特性之Optional类
NullPointException可以说是所有java程序员都遇到过的一个异常,虽然java从设计之初就力图让程序员脱离指针的苦海,但是指针确实是实际存在的,而java设计者也只能是让指针在java ...
- Java8 新特性之Stream API
1. Stream 概述 Stream 是Java8中处理集合的关键抽象概念,可以对集合执行非常复杂的查找,过滤和映射数据等操作; 使用 Stream API 对集合数据进行操作,就类似于使用 SQL ...
- Java8新特性——StreamAPI(二)
1. 收集器简介 收集器用来将经过筛选.映射的流进行最后的整理,可以使得最后的结果以不同的形式展现. collect方法即为收集器,它接收Collector接口的实现作为具体收集器的收集方法. Col ...
随机推荐
- 史上最全的select加锁分析(Mysql)
引言 大家在面试中有没遇到面试官问你下面六句Sql的区别呢 select * from table where id = ? select * from table where id < ? s ...
- java基础之IO流及递归理解
一.IO流(简单理解是input/output流,数据流内存到磁盘或者从磁盘到内存等) 二.File类(就是操作文件和文件夹的) 1.FIleFile类构造方法 注意:通过构造方法创建的file对象是 ...
- ZOJ 2588 Burning Bridges 割边(处理重边)
<题目链接> 题目大意: 给定一个无向图,让你尽可能的删边,但是删边之后,仍然需要保证图的连通性,输出那些不能被删除的边. 解题分析: 就是无向图求桥的题目,主要是提高一下处理重边的姿势. ...
- 【ORM框架】Spring Data JPA(一)-- 入门
本文参考:spring Data JPA入门 [原创]纯干货,Spring-data-jpa详解,全方位介绍 Spring Data JPA系列教程--入门 一.Spring Data JPA介 ...
- 第三方布局框架Neon初探
github地址:https://github.com/mamaral/Neon 居中 设置 view 在 superview 的中心,调用 anchorInCenter()并设置view大小,相当于 ...
- TimesTen数据库表中显示中文乱码的真正原因
上一篇博客TimesTen中文乱码问题(其实是cmd.exe中文乱码)的内容可能不对,也许只是个巧合?不得而知了.因为我今天重装系统了,把win10换成了win7(64bit).又安装了timeste ...
- 使用COOKIE实现登录 VS 使用SESSION实现登录
注:本文使用的代码基于PHP,其他语言逻辑同理. 一:使用COOKIE实现登录验证 使用cookie实现登录的方式,主要通过一些单向的加密信息进行验证.比如admin用户登录了之后,服务端生成一个co ...
- mysql 零碎笔记
聚合函数的用法: concat 连接单行记录的不同字段, group_concat 连接多行记录的相同字段, concat_ws count 按条件统计: SELECT COUNT(*) AS `nu ...
- javaEE学习路线与目标
1.Java基础知识(15-30天) 2.了解html+css+js+jq+bootstrap(7天) 3.mysql+jdbc(重点)(3天) 4.xml(1天) 5.http协议+tomcat(1 ...
- 接口自动化项目搭建(Java+testng+maven+git+springboot)
自动化测试: https://www.bilibili.com/video/av31078661?from=search&seid=16551153777362561361 一工具准备 二 环 ...