1. 简介

本文将深入对比 Collections.emptyList() 与新建 List 实例(如 new ArrayList<>())之间的关键差异。虽然两者都能表示一个空列表,但在实际开发中选择不当可能会踩坑,尤其在并发、性能和语义表达上。

2. 不可变性 ✅ vs 可变性 ❌

最核心的区别在于是否可变

  • Collections.emptyList() 返回的是一个不可变列表(确切类型是 java.util.Collections.EmptyList),任何修改操作(如 addremove)都会抛出 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(),语义更现代,推荐新项目使用。


原始标题:Collections.emptyList() vs. New List Instance | Baeldung

« 上一篇: Hazelcast Jet 介绍