ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

万恶的NPE差点让我半个月工资没了

2021-03-05 09:01:22  阅读:297  来源: 互联网

标签:万恶 return listUser NPE List 月工资 userList null


转:

万恶的NPE差点让我半个月工资没了

引言

最近看到《阿里巴巴Java开发手册》第11条规范写到:

防止 NPE ,是程序员的基本修养

NPE(Null Pointer Exception)一直是开发中最头疼的问题,也是最容易忽视的地方。记得刚开始工作的时候所在的项目组线上出现最多的bug不是逻辑业务bug而是NPE,所以后面项目组出了一个奇葩的规矩,线上如果谁出现一个NPE的问题就罚款100元,用作团建费用。如果项目组每个人一个月都出现个两三个NPE的话。那么项目组是不是每个月都可以去团建下(自己掏钱海吃海喝,心不心疼)。不过自从这个规矩实施以来,线上的NPE就渐渐的少了,从最初的一个月团建一次到最后的半年团建一次。大家写代码都比较谨慎了,只要用到对象或者集合的时候二话不说上来先判空,所以产生的NPE就少了。

业务中返回结果的空值

在我们常见的业务开发中是不是经常会有这样的接口:

package com.workit.demo.nullexcption;

import com.workit.demo.proxy.User;

import java.util.List;

public interface IUserSearchService {
  /**
   * 查询用户列表
   * @return
   */
  List listUser();

}

这个接口是不是存在两个潜在的问题?

  • listUser这个方法 如果没有数据,那它是返回空集合还是null呢?
  • getUserById 如果根据ID没有找到用户,是抛异常还是返回null呢?
    首先我们先看下listUser这个方法的实现:
 public List listUser() {
        List userList = userRepository.listUser();
        if (null == userList || userList.size() == 0) {
            return null;
        }
        return userList;
    }

这种实现如果调用者是一个严谨的人或者像我这样被NPE罚款买过单的人,是会对返回结果进行null的判断。如果调用者并非谨慎的人或者刚刚入门的人,他就会按照自己的理解去调用接口,拿到结果就不管三七二十一上来对结果就是一顿循环操作,而不进行是否为null的条件判断,如果这样的话,是非常危险的,它很有可能出现空指针异常!这就是在代码中埋了一个定时炸弹,不知道什么时候就会爆炸。
万恶的NPE差点让我半个月工资没了
由于存在这种不安全的隐患我们可以看下第二种实现:

  public List listUser() {
        List userList = userRepository.listUser();
        if (null == userList || userList.size() == 0) {
            return new ArrayList<>();
        }
        return userList;
    }

对于这种实现它一定会返回List,即使没有数据,也会返回一个空集合。通过以上的修改,我们成功的避免了有可能发生的空指针异常,这样的写法更安全!
那针对于上面的两种实现,一个是需要调用者进行判空,一个是提供接口的人返回默认值。那我们到底应该用哪种方式呢?这种情况《阿里巴巴开发手册》也有明确规定:
万恶的NPE差点让我半个月工资没了所以还是那句话使用任何对象或者集合之前记得先判空

业务中请求参数空值

 /**
   * 根据用户ID查询当前用户
   * @param id
   * @return
   */
  User getUserById(Integer id);

这个接口的描述,你能确定入参id一定是必传的吗? 我觉得答案应该是:不能确定。除非接口的文档注释上加以说明。那么我们应该怎样来约束入参呢?

  • 强制约束
  @Override
    public User getUserById(Integer id) {
        if (Objects.isNull(id)){
            throw new IllegalArgumentException("id不能为空");
        }
        return null;
    }

通过jsr 303进行严格的约束声明配合AOP的操作进行验证。

User getUserById(@NotNull  Integer id);

其他需要注意的NPE

switch中的空指针异常

看下面的列子妥妥的NPE

 public static void main(String[] args) {
        eat(null);
    }
     enum EatType{
         Breakfast,Lunch,Dinner;
    }
    public static void eat(EatType eatType){
        switch(eatType){
            case Breakfast:
                System.out.println("吃早饭");
                break;
            case Lunch:
                System.out.println("吃中饭");
                break;
            case Dinner:
                System.out.println("吃晚饭");
                break;
            default:
                System.out.println("输入错误");
                break;
        }
    }
数据库的sum函数

万恶的NPE差点让我半个月工资没了
如果price对应的所有的值为null,那么算出来的和为null
万恶的NPE差点让我半个月工资没了
如果采用ifnull函数就可以求和就是0这样就可以避免空指针。
万恶的NPE差点让我半个月工资没了

使用Map类集合时需要注意存储值为null的时候

笔者就是由于存储了null值造成生产事故,差点被开除了!详细介绍可以阅读以前文章《Java采坑记》
万恶的NPE差点让我半个月工资没了

使用 java.util.stream.Collectors 类的 toMap()方法注意value为空时

万恶的NPE差点让我半个月工资没了
如果项目里面就是有null值怎么办呢?可以用下面几种方法来解决:

  • 过滤值为null
  • 换一种写法
  • 据说这个问题java9就修复了,所以也可以尝试升级jdk
  List<pair<string, double="">> pairArrayList = new ArrayList<>(2);
        pairArrayList.add(new Pair<>("version1", 4.22));
        pairArrayList.add(new Pair<>("version2", null));
        // 第一种过滤值为null的
        Map<string, double=""> map = pairArrayList.stream().filter(p-> Objects.nonNull(p.getValue())).collect(
                Collectors.toMap(Pair::getKey, Pair::getValue, (v1, v2) -> v2));
        System.out.println(map.toString());
        // 换一种实现方式
        LinkedHashMap<object, object=""> collect = pairArrayList.stream().collect(LinkedHashMap::new, (m, v) -> m.put(v.getKey(), v.getValue()), LinkedHashMap::putAll);
        System.out.println(collect.toString());

标签:万恶,return,listUser,NPE,List,月工资,userList,null
来源: https://www.cnblogs.com/wangtcc/p/14484177.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有