程序员你是如何降低NPE的?
程序员,如果系统突然报了一个空指针异常,你肯定像吞了一只苍蝇一样尴尬。
那么如何在日常开发过程中降低NPE?
问题 | 回答 |
---|---|
现状 | 返回空值会出现大量的空指针异常 |
目的 | 改进方法的返回值,降低出现空指针异常 |
实现路径 | 方法返回空集合或者空数组 |
跟我来!
背景
下面的方法看起来很常见。
private final List<Chesse> chessesInStock= ... public List<Cheese> getCheeses(){ return cheesesInStock.isEmpty()?null:new ArrayList<>(cheesesInStock); }
假如你去购买芝士的时候没有可用的芝士,似乎没有理由特别指出这种场景。
但是你这么做的话,客户端需要添加额外代码来处理可能返回空值的情况。示例代码如下:
List<Cheese> cheeses = shop.getCheeses(); if(cheses != null && cheeses.contains(Cheese.STILTON)){ System.out.println("jolly good"); }
每一个返回空值的方法都使用上面这种处理方式,应该替换为返回一个空集合或者空数组。
这是一种错误的趋势,因为程序员些客户端代码可能会忘记写特殊代码来处理返回的空值。
这个错误可能会持续很长时间,因为这样的方法通常会返回一个或多个对象。
不返回空集合空数组的争论
返回空值替换为返回空容器也会使得方法的实现变得复杂。
通常争论的是:返回空值比返回空集合更好是因为创建一个空的容器有性能消耗。
这个论点不对,原因有两点:
一,没有必要担心性能除非有证据显示创建一个空容器整的有损性能;
二,你可以返回一个空集合或者数组而不用创建它们。
返回空集合
下面是一个典型的代码返回一个可能的空集合,通常,这就是你所需要的。
public List<Cheese> getCheeses(){ return new ArrayList<>(cheeseInStock); }
没有证据证明创建一个空集合会有损性能,你可以返回一个相同的不可变空集合来避免创建空集合。因为不可变对象是可以被自由共享的,下面是使用代码。
需求场景 | 代码 |
---|---|
空List | Collections.emptyList() |
空Set | Collections.emptySet() |
空Map | Collections.emptyMap() |
但是记住,以上这些操作是只是优化,很少被调用,如果你认为你需要它,在调用前后进行性能对比,确保它真的有用。
public List<Cheese> getCheeses(){ return cheesesInStock.isEmpty()?Collections.emptyList():new ArrayList<>(cheesesInStock); }
返回空数组
使用数组的场景跟集合是相同的,永远不要返回空值,应该返回一个长度位0的数组,常常,你应该简单的返回一个有适当长度的数组,也许长度是0。
注意我们传递一个长度为0的数组到toArray方法中来代表期望的返回类型;
public Cheese[] getCheeses(){ return cheesesInStock.toArray(new Cheese[0]); }
如果你认为创建一个长度为0的数组会降低性能,你可以返回同一个长度为0的数组,因为所有长度为0的数组都是不可变的;
private static final Cheese[] EMPTY_ARRAY= new Cheese[0]; public Cheeses[] getCheeses(){ return cheesesInStock.toArray(EMPTY_ARRAY); }
在优化版本中,我们传递了同一个空的数组到每一个toArray的调用,这个数组将会从getCheeses返回,无论cheesesInStock是不是空的,不要期望预分配数组可以提高性能,研究显示这是适得其反的。
return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);
小结
如果你只能记住一句话:返回空集合或者数组而不要返回空值。
返回空值会让你的API更难使用并且更容易出错,并且无性能优势;
原创不易,关注诚可贵,转发价更高!转载请注明出处,让我们互通有无,共同进步,欢迎沟通交流。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架