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 问题。