众所周知,null异常是java最常出现的异常类型。当我们调用service的时候有时候最多出现的就是null异常
一:业务实际场景
1.获取对象
public interface UserService{
/**
* 根据用户id获取用户信息
* @param id 用户id
* @return 用户实体
*/
User get(Integer id);
}
2.获取列表
public interface UserService{
List<User> listUser();
}
针对上面的代码,我们能保证数据库查询出来一定是User对象或者list吗?
listUser() 如果没有数据,那它是返回空集合还是null呢?
get(Integer id) 如果没有这个对象,是抛异常还是返回null呢?
二:接口实现优化
1:listUser方法
这个接口,我经常看到如下实现:
public List<User> listUser(){
List<User> userList = userService.listUser();
if(CollectionUtils.isEmpty(userList)){//spring util工具类
return null;
}
return userList;
}
这段代码返回是null,对于集合这样返回值,最好不要返回null,因为如果返回了null,会给调用者带来很多麻烦。你将会把这种调用风险交给调用者来控制。
如果调用者是一个谨慎的人,他会进行是否为null的条件判断。如果他并非谨慎,或者他是一个面向接口编程的狂热分子(当然,面向接口编程是正确的方向),他会按照自己的理解去调用接口,而不进行是否为null的条件判断,如果这样的话,是非常危险的,它很有可能出现空指针异常!
根据墨菲定律来判断: “很有可能出现的问题,在将来一定会出现!”
基于此,我们将它进行优化:
public List<User> listUser(){
List<User> userList = userService.listUser();
if(CollectionUtils.isEmpty(userList)){
return Lists.newArrayList();//guava类库提供的方式
}
return userList;
}
对于接口(List listUser()),它一定会返回List,即使没有数据,它仍然会返回List(集合中没有任何元素);
通过以上的修改,我们成功的避免了有可能发生的空指针异常,这样的写法更安全!
2:get方法
对于接口
User get(Integer id)
我们能看到的现象是,我给出id,它一定会给我返回User.
但事实真的很有可能不是这样的。
我看到过的实现:
public User get(Integer id){
return userService.get(id);//从数据库中通过id直接获取实体对象
}
相信很多人也都会这样写。
通过代码的时候得知它的返回值很有可能是null! 但我们通过的接口是分辨不出来的!
这个是个非常危险的事情。尤其对于调用者来说!
我们可以用Java8的Optional去诊断这个user是否为空
public User get(Integer id){
//从数据库中通过id直接获取实体对象
return Optional.ofNullable(userService.get(id)).orElseGet(()->new User());
}