《Effective Java》解读第54条:返回零长度的数组或者集合,而不是null

第54条:返回零长度的数组或者集合,而不是null

当方法返回一个数组或集合时,如果没有找到任何元素(即结果为空),应该返回一个零长度的数组或空集合,而不是返回 null。

为什么避免返回 null?

方法如果可以返回null,那么调用方需要进行检测,忘记检测会造成很常见的空指针错误。

java 复制代码
List<Cheese> cheeses = shop.getCheeses();
if (cheeses != null && cheeses.contains(Cheese.STILTON)) {
    System.out.println("Jolly good, just the thing.");
}

不同情况下null的影响:

  • 增强 for 循环:null 会直接抛异常,而空集合会正常跳过。

  • Stream API:null 无法直接调用 .stream(),而空集合可以。

  • Optional:即使使用 Optional,Optional.of(emptyList) 也比 Optional.ofNullable(null) 更清晰。

当然,你无法保证第三方一定不会返回null,所以一般调用第三方接口时,都会防御性的判断是否为空。

正确做法

一般情况,返回一个零长度的集合:

java 复制代码
public List<String> getNames() {
    if (noNames) {
        return Collections.emptyList();   // 不可变空列表
    }
    return new ArrayList<>(names);
}
java 复制代码
// The right way to return a possibly empty array
public Cheese[] getCheeses() {
    return cheesesInStock.toArray(new Cheese[0]);
}

相对于返回null,零数组的创建会消耗性能。

可以进行优化,返回Collections.emptyList(),这种纳秒级别优化,几乎用不到,为了节省一次 new ArrayList<>() 而引入特殊判断逻辑(isEmpty() ? emptyList() : new ArrayList<>(...))反而使代码更复杂、可读性下降,书中的原则一直是:首先写清晰正确的代码,只在必要时优化。

java 复制代码
// Optimization - avoids allocating empty collections
public List<Cheese> getCheeses() {
    return cheesesInStock.isEmpty() ? Collections.emptyList() : new ArrayList<>(cheesesInStock);
}

利用 Collections.emptyList() 返回一个不可变的空列表,多次调用返回的是同一个对象,避免了重复分配的开销。如果返回 Set 则使用 Collections.emptySet(),返回 Map 则使用 Collections.emptyMap()。

注意:

java 复制代码
// √
cheesesInStock.toArray(new Cheese[0])
// ×
cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);

不要为其预设大小,这种做法反而会损害性能,适得其反。

总结

永远不要返回 null,而应该返回一个零长度的数组或者集合。如果返回 null,那么会使 API 更难使用,也更容易出错,而且没有任何性能优势。

相关推荐
傻啦嘿哟5 小时前
某招聘平台爬虫:爬取招聘岗位数据,分析各城市薪资水平
开发语言·爬虫·python
2501_933670795 小时前
2026秋招量化分析岗技能栈:Python、SQL、统计建模、回测项目怎么准备
开发语言·python·sql
2601_962077605 小时前
python Dejavu库快速识别音频指纹实例探究
python·音乐识别·dejavu库·音频指纹识别·实例探究
yxlalm5 小时前
Spring AI+RAG 01-项目背景与技术选型
java·人工智能·spring
科技苑5 小时前
如何用Python编程实现一个简单的Web爬虫?
人工智能·python
程序员清风6 小时前
Java 后端高并发设计:线程池、限流、熔断与降级
java·数据库·oracle
李少兄6 小时前
JavaScript 数据类型完全指南
开发语言·javascript·ecmascript
dayDayupbetter6 小时前
Visual C++ 2010安装与使用高手秘籍
python
隐擎fox6 小时前
深入理解网络传输层安全:TLS 指纹识别(JA3/JA4)原理与 Python 协议层检测实战
爬虫·python·网络协议·安全·网络安全·https
医疗信息化王工6 小时前
DataForge:基于 Python 的数据库批量导出 Excel 工具——从架构到部署的全流程实战
数据库·python·excel