牛逼,这2招,彻底让你和 null say 拜拜-阿里云开发者社区

开发者社区> 沉默王二> 正文

牛逼,这2招,彻底让你和 null say 拜拜

简介: 牛逼,这2招,彻底让你和 null say 拜拜
+关注继续查看

你好呀,我是沉默王二,一个和黄家驹一样身高,和刘德华一样颜值的程序员。从 10 年前我开始写第一行 Java 代码至今,一直觉得 null 在 Java 中是一个最特殊的存在,它既是好朋友,可以把不需要的变量置为 null 从而释放内存,提高性能;它又是敌人,因为它和大名鼎鼎且烦不胜烦的 NullPointerException(NPE)如影随形,而 NPE 的发明人 Tony Hoare 曾在 2009 年承认:“Null References 是一个荒唐的设计,就好像我赌输掉了十亿美元”。




你看,null 竟然是一个亦敌亦友的家伙。


通常,为了表示列表中的元素不存在,我们首先想到的就是返回 null,这种想法很合理,合理到无法反驳。我们来模拟一个实际的应用场景,假设小二现在要从数据库中获取一个姓名的列表,然后将姓名打印到控制台,对应的代码如下。


public class NullDemo {
    public static void main(String[] args) {
        List<String> names = getNamesFromDB();
        if (names != null) {
            for (String name : names) {
                System.out.println(name);
            }
        }
    }
    public static List<String> getNamesFromDB() {
        // 模拟此时没有从数据库获取到对应的姓名。
        return null;
    }
}



由于 getNamesFromDB() 方法返回了 null 来作为没有姓名列表的标志,那就意味着在遍历列表的时候要先对列表判空,否则将会抛出 NPE 错误,不信你把 if (names != null) 去掉试试,立马给你颜色看。


Exception in thread "main" java.lang.NullPointerException

at com.cmower.dzone.stopdoing3things.NullDemo.main(NullDemo.java:12)



那假如小二在遍历的时候不想判空又不想代码抛出 NPE 错误,他该怎么做呢?闭上你的大眼睛好好想一想。




嗯,报告,我想出来了,建议小二从数据库中获取姓名的时候返回长度为 0 的列表,来表示未找到数据的情况。代码示例如下所示:


public class Null2Length0Demo {
    public static void main(String[] args) {
        List<String> names = getNamesFromDB();
        for (String name : names) {
            System.out.println(name);
        }
    }
    public static List<String> getNamesFromDB() {
        // 模拟此时没有从数据库获取到对应的姓名。
        return Collections.emptyList();
    }
}



注:Collections.emptyList() 用于返回一个不可变的空列表,能理解吧?假如不能理解的话,我再写一个返回可变的空列表的示例,你对比着感受一下就理解了。


public class Null2Length0MutableDemo {
    public static void main(String[] args) {
        List<String> names = getNamesFromDB();
        for (String name : names) {
            System.out.println(name);
        }
    }
    public static List<String> getNamesFromDB() {
        // 模拟此时没有从数据库获取到对应的姓名。
        return new ArrayList<>();
    }
}



new ArrayList<>() 返回的就是可变的,意味着你还可以改变这个列表的元素,比如说增加,删除是不可能的了,因为本身就没有元素可删。


你看,Collections.emptyList() 和 new ArrayList<>() 都可以替代 null,来减少打印列表时不必要的判空以及那个讨厌的家伙——NPE。


除了我这个想法之外,你还能想到其他的解决方案吗?来,再次闭上你的大眼睛,替小二想一想,没准你还能想到一个—— Java 8 新增的 Optional 类,一个容器类,可以存放任意类型的元素,如果值存在则

isPresent() 方法会返回 true;Optional 类提供了很多专业的方法而不用显式进行空值检查,从而巧妙地消除了 NPE。


来,先读示例为快!


public class Null2OptionalDemo {
    public static void main(String[] args) {
        Optional<List<String>> list = getNamesFromDB();
        list.ifPresent(names -> {
            for (String name : names) {
                System.out.println(name);
            }
        });
    }
    public static Optional<List<String>> getNamesFromDB() {
        boolean hasName = true;
        if (hasName) {
            String [] names = {"沉默王二", "一枚有趣的程序员", "微信搜索关注我"};
            return Optional.of(Arrays.asList(names));
        }
        return Optional.empty();
    }
}

看得不太懂?我来负责任地介绍一下,你们握个手。


假如数据库中存在姓名,则使用 Optional.of() 对返回值进行包装,从而返回一个 Optional 类型的对象。为什么不用构造方法呢,因为构造方法是 private 的(源码如下所示)。


private Optional(T value) {

   this.value = value;

}



那为什么要用 Optional.of() 呢?嗯,good question。继续上源码。


public static <T> Optional<T> of(T value) {

   return new Optional<>(Objects.requireNonNull(value));

}



1)如果 value 为 null,那么 Objects.requireNonNull(value) 就会抛出 NPE(嗯哼,总归是要碰面的,但好歹不用我们程序员主动 check 了)。


2)如果 value 不为 null,则通过 new 关键字创建正常的 Optional 对象。


假如数据库中不存在姓名呢?使用 Optional.empty() 作为返回值。来,继续上源码。


public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}


嗯哼,EMPTY 是什么玩意?


private static final Optional<?> EMPTY = new Optional<>(null);

1

竟然是 Optional 类的一个私有常量(static + final)。怎么此刻我的脑子里想起了安徒生先生的寓言故事——皇帝的新衣,嗯,甭管了,反正“底层终究是丑陋的”。


这样的话,就可以使用 Optional 对象的 ifPresent() 方法来判断值是否存在,如果只需要处理值存在的情况,就可以使用 Lambda 表达式的方式直接打印姓名。


list.ifPresent(names -> {

   for (String name : names) {

       System.out.println(name);

   }

});


有点简单粗暴,对不对?但不管怎么说,终于可以在表象上和 null,NPE 说拜拜了,做人嘛,开心点。




好了,我亲爱的读者朋友,以上就是本文的全部内容了,能看到这里的就是最优秀的程序员。原创不易,莫要白票,请你为本文点赞个吧,这将是我写作更多优质文章的最强动力。


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
9950 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
11565 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13695 0
windows server 2008阿里云ECS服务器安全设置
最近我们Sinesafe安全公司在为客户使用阿里云ecs服务器做安全的过程中,发现服务器基础安全性都没有做。为了为站长们提供更加有效的安全基础解决方案,我们Sinesafe将对阿里云服务器win2008 系统进行基础安全部署实战过程! 比较重要的几部分 1.
9130 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
4641 0
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
7450 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,云吞铺子总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系统盘、创建快照、配置安全组等操作如何登录ECS云服务器控制台? 1、先登录到阿里云ECS服务器控制台 2、点击顶部的“控制台” 3、通过左侧栏,切换到“云服务器ECS”即可,如下图所示 通过ECS控制台的远程连接来登录到云服务器 阿里云ECS云服务器自带远程连接功能,使用该功能可以登录到云服务器,简单且方便,如下图:点击“远程连接”,第一次连接会自动生成6位数字密码,输入密码即可登录到云服务器上。
22335 0
+关注
沉默王二
微信搜索「沉默王二」,回复关键字「00」获取硬核计算机基础资料。
1084
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载