用 Stream.empty() 创建空流是预防空指针最直接有效的方式——它返回一个确定不为 null 的、已初始化的空流对象,避免后续 map、filter 等操作因上游为 null 而抛出 NullPointerException。

用 Stream.empty() 创建空流是预防空指针最直接有效的方式——它返回一个确定不为 null 的、已初始化的空流对象,避免后续 map、filter 等操作因上游为 null 而抛出 NullPointerException。
为什么不能直接用 null 代替空流
Java 流不是可空容器,Stream 类型设计上就不鼓励 null 值传递。一旦方法返回 null,调用方必须显式判空,否则链式调用(如 stream.map(...).filter(...).collect(...))会在第一步就崩溃。
-
null不是Stream实例,无法调用任何流方法 - 强制判空会污染业务逻辑,让代码变臃肿、易遗漏
- 违反“空对象模式”原则:应提供有行为的空实例,而非用
null表示“无”
正确使用 Stream.empty() 的典型场景
核心原则:**所有可能为空的流来源,都应统一兜底为 Stream.empty()**。
- 集合为空时:
list == null ? Stream.empty() : list.stream() - Optional 转流:
optional.map(Collection::stream).orElse(Stream.empty())(注意不是orElse(null)) - 条件分支中提前退出:
if (skip) return Stream.empty(); else return data.stream(); - 工具方法封装:
public static <T> Stream<T> safeStream(Collection<T> c) { return c == null ? Stream.empty() : c.stream(); }
配合 Optional 和 Collections.emptyList() 更稳妥
Stream.empty() 解决的是流本身非空问题,但上游数据源(如集合、数组)仍可能为 null。建议组合使用:
- 对集合参数先做防御性复制:
Objects.requireNonNullElse(collection, Collections.emptyList()).stream() - 与
Optional协同:把可能为null的对象包装成Optional.ofNullable(obj),再 flatMap 到流 - 避免反模式:
return someList != null ? someList.stream() : null;—— 这仍是隐患源头
单元测试中验证空流行为
空流应安静完成,不抛异常、不执行副作用、返回预期空结果:
- 断言
stream.count() == 0 - 断言
stream.findFirst().isEmpty() - 若流中含 map 操作,确保 lambda 不被调用(可用 Mockito spy 验证)
- 对比测试:分别用
Stream.empty()和null输入,确认前者稳定通过,后者失败
空流不是特殊处理,而是默认契约。坚持用 Stream.empty() 替代 null,能让流式代码更健壮、更可读、更易维护。


















