1. 简介
本文将深入对比 Collections.emptyList()
与新建 List 实例(如 new ArrayList<>()
)之间的关键差异。虽然两者都能表示一个空列表,但在实际开发中选择不当可能会踩坑,尤其在并发、性能和语义表达上。
2. 不可变性 ✅ vs 可变性 ❌
最核心的区别在于是否可变。
Collections.emptyList()
返回的是一个不可变列表(确切类型是java.util.Collections.EmptyList
),任何修改操作(如add
、remove
)都会抛出UnsupportedOperationException
。- 而
new ArrayList<>()
创建的是一个可变列表,可以自由增删元素。
示例代码对比
@Test
public void givenArrayList_whenAddingElement_addsNewElement() {
List<String> mutableList = new ArrayList<>();
mutableList.add("test");
assertEquals(mutableList.size(), 1);
assertEquals(mutableList.get(0), "test");
}
@Test(expected = UnsupportedOperationException.class)
public void givenCollectionsEmptyList_whenAdding_throwsException() {
List<String> immutableList = Collections.emptyList();
immutableList.add("test");
}
⚠️ 注意:
Collections.emptyList()
返回的列表是全局共享的单例实例,因此“不可变”不仅是语义上的,更是线程安全的。
3. 对象创建机制:只创建一次 ✅
Collections.emptyList()
的设计非常高效——它只会创建一次空列表对象,后续调用都返回同一个静态实例。
查看 JDK 源码即可确认:
public static final List EMPTY_LIST = new EmptyList<>();
public static final <T> List<T> emptyList() {
return (List<T>) EMPTY_LIST;
}
这意味着:
- 多次调用
Collections.emptyList()
不会产生额外的对象开销。 - 在高并发或频繁初始化场景下,性能优势明显。
- 节省内存,避免重复创建无意义的空对象。
相比之下,new ArrayList<>()
每次都会分配新对象,哪怕你只是想要一个“空”的容器。
4. 代码可读性与意图表达 ✅
使用 Collections.emptyList()
能更清晰地传达你的编码意图:我明确需要一个空的、不可变的列表。
而 new ArrayList<>()
更像是“我需要一个可变列表,目前恰好为空”。
举个实际场景
假设你在写一个接口返回值:
public List<User> findUsersByRole(String role) {
if (StringUtils.isEmpty(role)) {
return Collections.emptyList(); // 明确表达:这里返回空结果是合法且预期的
}
// ... 查询逻辑
}
✅ 使用 Collections.emptyList()
更能体现“空结果是正常业务路径”的设计思想。
❌ 若用 new ArrayList<>()
,读者可能会疑惑:“这个列表之后会不会被修改?”、“是不是忘了初始化数据?”
5. 总结
对比维度 | Collections.emptyList() |
new ArrayList<>() |
---|---|---|
可变性 | ❌ 不可变(安全) | ✅ 可变 |
对象创建 | ✅ 单例复用,零开销 | ❌ 每次新建,有 GC 压力 |
内存占用 | ✅ 极低 | ❌ 累积浪费 |
线程安全 | ✅ 是(不可变) | ❌ 否(需额外同步) |
语义表达 | ✅ “我就是要一个空列表” | ⚠️ “我可能要往里加东西” |
推荐使用场景
- ✅ 返回空集合(API 接口、工具方法)
- ✅ 初始化默认值(如配置未命中时的 fallback)
- ✅ 需要不可变空列表的任何场景
什么时候用 new ArrayList<>()
?
只有当你明确需要后续添加元素时才使用。否则,优先考虑 Collections.emptyList()
。
💡 小贴士:Java 9+ 中也可以使用
List.of()
来创建不可变集合,例如List.of()
等价于Collections.emptyList()
,语义更现代,推荐新项目使用。