终于和 null say 拜拜了,我超开心
![](http://static.careerengine.us/api/aov2/http%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_jpg_%7C_C1uDMDqjn18aujY28jvryWWp9pPZkXibQpZv8CPSTcSOUicuGLkmQPFGDbP9JogcWaF5R7fiawyGFR1ZaDyjCP9sA_%7C_0%3Fwx_fmt%3Djpeg.jpg)
从 10 年前我开始写第一行 Java 代码至今,一直觉得 null 在 Java 中是一个最特殊的存在,它既是好朋友,可以把不需要的变量置为 null 从而释放内存,提高性能;它又是敌人,因为它和大名鼎鼎且烦不胜烦的
NullPointerException
(NPE)如影随形,而 NPE 的发明人 Tony Hoare 曾在 2009 年承认:“Null References 是一个荒唐的设计,就好像我赌输掉了十亿美元”。![](http://static.careerengine.us/api/aov2/https%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_png_%7C_z40lCFUAHpl1C82ILZAqGfT5z2ZCJNiaqHydGMo5BJoibia9kexznQpqlpRLiaIqHZxC0SIE3SicDicficKpHficWyKkaQ_%7C_640%3Fwx_fmt%3Dpng.jpg)
你看,null 竟然是一个亦敌亦友的家伙。
通常,为了表示列表中的元素不存在,我们首先想到的就是返回 null,这种想法很合理,合理到无法反驳。我们来模拟一个实际的应用场景,假设小二现在要从数据库中获取一个姓名的列表,然后将姓名打印到控制台,对应的代码如下。
publicclassNullDemo{
publicstaticvoidmain(String[] args){
List<String> names = getNamesFromDB();
if (names != null) {
for (String name : names) {
System.out.println(name);
}
}
}
publicstatic List<String> getNamesFromDB(){
// 模拟此时没有从数据库获取到对应的姓名。
returnnull;
}
}
由于
getNamesFromDB()
方法返回了 null 来作为没有姓名列表的标志,那就意味着在遍历列表的时候要先对列表判空,否则将会抛出 NPE 错误,不信你把 if (names != null)
去掉试试,立马给你颜色看。Exceptioninthread "main" java.lang.NullPointerException
atcom.cmower.dzone.stopdoing3things.NullDemo.main(NullDemo.java:12)
那假如小二在遍历的时候不想判空又不想代码抛出 NPE 错误,他该怎么做呢?闭上你的大眼睛好好想一想。
![](http://static.careerengine.us/api/aov2/https%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_png_%7C_z40lCFUAHpl1C82ILZAqGfT5z2ZCJNiaqa2vCSEFmdGbW9M8mJprZtiaTsxqSKUwQYR5U6Z718ELpcUx0HCVYCuw_%7C_640%3Fwx_fmt%3Dpng.jpg)
嗯,报告,我想出来了,建议小二从数据库中获取姓名的时候返回长度为 0 的列表,来表示未找到数据的情况。代码示例如下所示:
publicclassNull2Length0Demo{
publicstaticvoidmain(String[] args){
List<String> names = getNamesFromDB();
for (String name : names) {
System.out.println(name);
}
}
publicstatic List<String> getNamesFromDB(){
// 模拟此时没有从数据库获取到对应的姓名。
return Collections.emptyList();
}
}
注:
Collections.emptyList()
用于返回一个不可变的空列表,能理解吧?假如不能理解的话,我再写一个返回可变的空列表的示例,你对比着感受一下就理解了。publicclassNull2Length0MutableDemo{
publicstaticvoidmain(String[] args){
List<String> names = getNamesFromDB();
for (String name : names) {
System.out.println(name);
}
}
publicstatic List<String> getNamesFromDB(){
// 模拟此时没有从数据库获取到对应的姓名。
returnnew ArrayList<>();
}
}
new ArrayList<>()
返回的就是可变的,意味着你还可以改变这个列表的元素,比如说增加,删除是不可能的了,因为本身就没有元素可删。你看,
Collections.emptyList()
和 new ArrayList<>()
都可以替代 null,来减少打印列表时不必要的判空以及那个讨厌的家伙——NPE。除了我这个想法之外,你还能想到其他的解决方案吗?来,再次闭上你的大眼睛,替小二想一想,没准你还能想到一个—— Java 8 新增的 Optional 类,一个容器类,可以存放任意类型的元素,如果值存在则
isPresent()
方法会返回 true;Optional 类提供了很多专业的方法而不用显式进行空值检查,从而巧妙地消除了 NPE。
来,先读示例为快!
publicclassNull2OptionalDemo{
publicstaticvoidmain(String[] args){
Optional<List<String>> list = getNamesFromDB();
list.ifPresent(names -> {
for (String name : names) {
System.out.println(name);
}
});
}
publicstatic Optional<List<String>> getNamesFromDB() {
boolean hasName = true;
if (hasName) {
String [] names = {"漫话编程"};
return Optional.of(Arrays.asList(names));
}
return Optional.empty();
}
}
看得不太懂?我来负责任地介绍一下,你们握个手。
假如数据库中存在姓名,则使用
Optional.of()
对返回值进行包装,从而返回一个 Optional 类型的对象。为什么不用构造方法呢,因为构造方法是 private 的(源码如下所示)。privateOptional(T value){
this.value = value;
}
那为什么要用
Optional.of()
呢?嗯,good question。继续上源码。publicstatic <T> Optional<T> of(T value){
returnnew Optional<>(Objects.requireNonNull(value));
}
1)如果 value 为 null,那么
Objects.requireNonNull(value)
就会抛出 NPE(嗯哼,总归是要碰面的,但好歹不用我们程序员主动 check 了)。2)如果 value 不为 null,则通过 new 关键字创建正常的 Optional 对象。
假如数据库中不存在姓名呢?使用
Optional.empty()
作为返回值。来,继续上源码。publicstatic<T> Optional<T> empty(){
@SuppressWarnings("unchecked")
Optional<T> t = (Optional<T>) EMPTY;
return t;
}
嗯哼,EMPTY 是什么玩意?
privatestaticfinal Optional<?> EMPTY = new Optional<>(null);
竟然是 Optional 类的一个私有常量(static + final)。怎么此刻我的脑子里想起了安徒生先生的寓言故事——皇帝的新衣,嗯,甭管了,反正“底层终究是丑陋的”。
这样的话,就可以使用 Optional 对象的
ifPresent()
方法来判断值是否存在,如果只需要处理值存在的情况,就可以使用 Lambda 表达式的方式直接打印姓名。list.ifPresent(names -> {
for (String name : names) {
System.out.println(name);
}
});
有点简单粗暴,对不对?但不管怎么说,终于可以在表象上和 null,NPE 说拜拜了,做人嘛,开心点。
推荐阅读:
![](http://static.careerengine.us/api/aov2/https%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_png_%7C_C1uDMDqjn1ibHbCU2uStzgickicPVx8dTvXsJx0bSBicMffyV0l2A9ZhFLJ6yNf4sydFpfCw8hVpsv9A3JNY0yYibfA_%7C_640.jpg)
![](http://static.careerengine.us/api/aov2/https%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_png_%7C_C1uDMDqjn1ibHbCU2uStzgickicPVx8dTvXsJx0bSBicMffyV0l2A9ZhFLJ6yNf4sydFpfCw8hVpsv9A3JNY0yYibfA_%7C_640.jpg)
![](http://static.careerengine.us/api/aov2/https%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_jpg_%7C_C1uDMDqjn1ibHbCU2uStzgickicPVx8dTvXD3xBw8gjLD3G1dwCPXfbkpUrYaWHlzBDMGGpVvueiaaAYtAEEkcQicHw_%7C_640%3Fwx_fmt%3Djpeg.jpg)
![](http://static.careerengine.us/api/aov2/https%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_jpg_%7C_C1uDMDqjn18LPQfZkBTzR42LiapBhhiaUxHBbrQnlkxzZqZGfgiaq4G7gHadvQibhVqGpeYMNcc9KkdVLibKia2XJHkg_%7C_640%3Fwx_fmt%3Djpeg.jpg)
好文章,我 在看
![](http://static.careerengine.us/api/aov2/https%3A_%7C__%7C_mmbiz.qpic.cn_%7C_mmbiz_jpg_%7C_C1uDMDqjn19wtuQpK3jmJW3bFGWI8Yz6FR17tl1MF8VfqYxPx990kv2J74Lvqwib26KayHdOXd6ebzrqYibbTjww_%7C_640%3Fwx_fmt%3Djpeg.jpg)
最新评论
推荐文章
作者最新文章
你可能感兴趣的文章
Copyright Disclaimer: The copyright of contents (including texts, images, videos and audios) posted above belong to the User who shared or the third-party website which the User shared from. If you found your copyright have been infringed, please send a DMCA takedown notice to [email protected]. For more detail of the source, please click on the button "Read Original Post" below. For other communications, please send to [email protected].
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。
版权声明:以上内容为用户推荐收藏至CareerEngine平台,其内容(含文字、图片、视频、音频等)及知识版权均属用户或用户转发自的第三方网站,如涉嫌侵权,请通知[email protected]进行信息删除。如需查看信息来源,请点击“查看原文”。如需洽谈其它事宜,请联系[email protected]。