这一周继续聊一聊Java 8之后的那些新特性,今天聊一个看似价值不大的新特性,但实质它却与Java语言的一个经常出错的异常有关联。
写Java程序的,无论如何也不会不知道一个异常,那就是NullPointerException,也就是空指针异常。在Java程序的世界中,相当一部分的错误可能都可以归类到这个错误。
而我记得早些年我在用Java做Android时,引发App闪退的最多的一个原因就是NullPointerException。而如果你用Kotlin来写Android,则这个错误可以大大减少。
这是Java 8之后的那些新特性系列的第五篇,这个系列其它文章为:
- 1. Java 8之后的那些新特性(一):局部变量var
- 2. Java 8之后的那些新特性(二):文本块 Text Blocks
- 3. Java 8之后的那些新特性(三):Java System Logger
- 4. Java 8之后的那些新特性(四):网络请求 Java Http Client
one billion dollar mistake
在编程的行业中,也许你听到过一个说法,那就是"one billion dollar mistake",用中文来说就是十亿美元的错误
这个讲的是什么呢,其实它讲的就是Null References这个概念。
Null References是Richard Hoare在1965年发明的,当时他主导设计一门面向对象的语言ALGOL W,基于所有指针引用安全的考量,设计出了Null References。而Java语言后面则同样实现了这个设计。
这个设计被Richard Hoare后面自我反省为一个错误,称因为这个设计,引发了巨大的经济上的损失。许多程序上的错误可能就是因为检查空这个没有做,导致系统服务不正常,应用App闪退等。
Richard Hoare称之为one billion dollar mistake。
Java的改进
而事实上,只要在设计上稍等改变,就可以避免这个错误,使得程序更健壮。现代的一些诸如Kotlin或Swift等语言就在语言设计上避免开了这个问题。
当然,Java这个问题点上也不是说没有改进,在Java 8时Java 引进了Optional的概念,而在Java 14的时候,又引进了Helpful NullPointerExceptions。
Optional这个立意虽然不错,但实质上它对解决Java这个NullPointerException并无太多实质帮助,这个可以我后面单独再详细聊一聊这个点。
而今天我要聊的Helpful NullPointerExceptions则并不是为了解决NullPointerException,它是为了解决NullPointerException异常信息中有时出现的混淆的错误。
NullPointerException的混淆
在Java 8为主流的情况下,当你的代码遇上NullPointerException的时候,有时候是很难搞的清具体是谁导致的空指针异常。
以如下代码为例:
代码语言:javascript复制 @Test
void testNullPointerException(){
Employee employee = randomEmployee();
String addressName = employee.getAddress().getName();
}
在这个代码中,如果遇上空指针异常,你得到的信息提示是:
代码语言:javascript复制Exception in thread "main" java.lang.NullPointerException
这个空指针异常会带来的混淆就是,你不能从这个错误的提示上明确,究竟是employee为空,还是address.getAdress()得到的Address实例为空,这两种情况都可能会导致这个错误。
所以呢,在Java 14的时候,对这个点做了优化,添加了Helpful NullPointerExceptions
Helpful NullPointerExceptions
Helpful NullPointerExceptions的目的就只有一个:
让空指针异常提供更为明确,不会引发混淆
当你在使用Java 14以及之后的JDK版本时,上面这段同样的代码,你得到异常提示信息就是:
代码语言:javascript复制java.lang.NullPointerException: Cannot invoke "org.myddd.mock.Employee.getAddress()" because "employee" is null
看到没,这个提示相比过往,是不是更明确了,不会引发你的混淆了呢?
回到NullPointerException
好了,这个特性就是这么简单的一个特性,对Java这门语言来说,考虑到存在大量的NullPointerException,也还是挺有作用的。
那回到我在前面所说的一个问题就是,就Java 8的Optional特性而言,一方面你会发现实际使用这个特性的人很少,大家基本还是按照旧有方式来写Java代码,另一方面你就算使用Optional来写你的代码,也还是避免不了NullPointerException呢。
这是一个很有趣的问题,特别是当你参考同类语言,诸如Kotlin或Swift是如何来处理这个点时,就会对这个现象有更深刻的理解。
我们可以好好思考及探究下这现象及背后的原因。
后续写完这个系列,我再专门来聊一聊这个有趣的现象及我的理解。
这周就是这样了,下周还是聊Java 8之后的那些新特性。
在Java语言中,很多人会非常喜欢用一个叫lombok这个框架来简化Java的代码,而我个人是不主张使用类似的东西。而在Java中,实质上引入了另一个特性,那就是Record Class,它也有着非常类似的效果。
下周就聊一聊Record Class这个新特性,可以说它是Java 8之后非常有价值的一个新特性了。