java 如何优雅地处理空值

2021-06-10  本文已影响0人  飞鹰雪玉

场景

存在一个UserService用来提供用户查询的功能。

public interface UserService(){
        List<User> list();
        User getUser(Integer id);
}

疑惑

list():如果没有数据,返回null还是空集合?
getUser(Integer id):如果没有对应id的用户,返回null还是抛一个异常?

分析

先分析list()

一般实现有这样:

        public List<User> list(){
            List<User> userList = userMapper.list();
            if (userList.size() == 0){
                return null;
            }
            return userList;
        }

这段代码返回是null, 对于集合这样返回值,最好不要返回null,因为如果返回了null,会给调⽤者带 来很多麻烦。你将会把这种调用风险交给调用者来控制。
如果调用者是⼀个谨慎的⼈,他会进⾏是否为null的条件判断。如果他并⾮谨慎,或者他是⼀个⾯向接⼝编程的狂热分⼦(当然, ⾯向接⼝编程是正确的⽅向),他会按照⾃⼰的理解去调⽤接⼝,⽽不进⾏是否为null的条件判断,如果这样的话,是⾮常危险 的,它很有可能出现空指针异常!

为此我们进行优化:

        public List<User> list(){
            List<User> userList = userMapper.list();
            if (userList.size() == 0){
                return new ArrayList<>();
            }
            return userList;
        }

对于list()接口来说,它⼀定会返回List,即使没有数据,它仍然会返回List(集合中没有任何元素);
通过以上的修改,我们成功的避免了有可能发⽣的空指针异常,这样的写法更安全!

getUser(Integer id)

一般实现方式有以下

        public User getUser(Integer id){
            return userMapper.selectById(id);
        }

通过代码的时候得知它的返回值很有可能是null! 但我们通过的接⼝是分辨不出来的! 这个是个⾮常危险的事情。尤其对于调⽤者来说!
解决方案一:
在接口说明时补充⽂档,⽐如对于异常的说明,使⽤注解@exception:

        /**
         * 根据id获取用户对象
         * @param 用户id
         * @return 用户对象
         * @exception UserNotFoundException
         */
        User getUser(Integer id);

我们把接⼝定义加上了说明之后,调⽤者会看到,如果调⽤此接⼝,很有可能抛出UserNotFoundException这样的异常。这种⽅式可以在调⽤者调⽤接⼝的时候看到接⼝的定义,但是,这种⽅式是“弱提⽰”的!如果调⽤者忽略了注释,有可能就对业务系统产⽣了⻛险,这个⻛险有可能导致⼀个亿!

解决方案二:
引⼊jdk8的Optional,或者使⽤guava的Optional

        /**
         * 根据id获取用户对象
         * @param 用户id
         * @return 用户对象
         */
        Optional<User> getUser(Integer id);

Optional有两个含义: 存在 or 缺省。
实现

        public Optional<User> getUser(Integer id){
            return Optional.ofNullable(userMapper.selectById(id));
        }
上一篇 下一篇

猜你喜欢

热点阅读