NPE产生的场景:

1 )、返回类型为基本数据类型,return 包装数据类型的对象时,自动拆箱有可能产生 NPE。

反例: public int f() { return Integer 对象}, 如果为 null ,自动解箱抛 NPE 。

2 )、数据库的查询结果可能为 null 。

User user = userDao.loadUserByUsername(login.getUsername());
if (null == user) {
      return Result.operating("用户名不存在", false);
}

3 )、集合里的元素即使 isNotEmpty ,取出的数据元素也可能为 null 。

public class Demo012 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("黄晓明");
        list.add("杨颖");
        list.add("马伊琍");
        list.add(null);

        if(CollectionUtils.isNotEmpty(list)){
            // 去除集合中的null
//            list.removeAll(Collections.singleton(null));
            list.stream().forEach(item -> {
//                if(null != item){
                    String s = item.toString();
                    System.out.println(s);
//                }
            });
        }
    }
}

结果:

黄晓明
杨颖
马伊琍
Exception in thread "main" java.lang.NullPointerException
    at com.zwh.Demo012.lambda$main$0(Demo012.java:25)
    at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1494)
    at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:591)
    at com.zwh.Demo012.main(Demo012.java:23)

修改:

public class Demo012 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("黄晓明");
        list.add("杨颖");
        list.add("马伊琍");
        list.add(null);

        if(CollectionUtils.isNotEmpty(list)){
            // 取出集合中的null
            list.removeAll(Collections.singleton(null)); // 先通过singleton方法返回null的集合,再从List中删除所有的该对象
            list.stream().forEach(item -> {
//                if(null != item){
                    String s = item.toString();
                    System.out.println(s);
//                }
            });
        }
    }
}

结果:

黄晓明
杨颖
马伊琍

Collections的singleton方法如下:

返回只包含特定对象的集合,集合size为1。

public static <T> Set<T> singleton(T o) {
        return new SingletonSet<>(o);
    }

案例:

public class Demo014 {
    public static void main(String[] args) {
        String init[] = { "One", "Two", "Three", "One", "Two", "Three" };
        List list1 = new ArrayList(Arrays.asList(init));
        List list2 = new ArrayList(Arrays.asList(init));
        list1.remove("One"); // 只会删除第一个
        System.out.println(list1); // [Two, Three, One, Two, Three]
        list2.removeAll(Collections.singleton("One"));
        System.out.println(list2); // [Two, Three, Two, Three]
    }
}

注意:使用list2.removeAll(Collections.singleton("One"));会删除所有的指定的对象。

4 )、远程调用返回对象时,一律要求进行空指针判断,防止 NPE 。

@Reference
private ISaleOrderService saleOrderService;
// 远程调用
result = saleOrderService.querySaleOrder(Integer.valueOf(pageIndex), Integer.valueOf(pageSize));
if(null !=result){
systemLogDto.setOutParam(result.toString());
}

如果不进行空指针判断,有可能会出现空指针异常。

5 )、对于 Session 中获取的数据,建议 NPE 检查,避免空指针。

//根据加密后的用户获取用户的模和指数
Object modulus = session.getAttribute(RsaUserId.toUpperCase()+"_modulus");
Object private_exponent = session.getAttribute(RsaUserId.toUpperCase()+"_private_exponent");
if(null == modulus || null == private_exponent || StringUtil.isEmpty(RsaUserId) || StringUtils.isEmpty(RsaPasswd)) {
     json.put("result", false);
     json.put("type", getText("dcadmin_loginpage_tip_act_useraction4"));
     PrintUtil.printJson(json);
     return;
}

6 )、级联调用 obj . getA() . getB() . getC(); 一连串调用,易产生 NPE 。

正例:使用 JDK8 的 Optional 类来防止 NPE 问题。

posted on 2022-02-10 11:49  周文豪  阅读(506)  评论(1编辑  收藏  举报