new ArrayList(0) 与无参构造本质不同:前者使用 EMPTY_ELEMENTDATA,不触发默认扩容至10的逻辑,而是按需计算最小容量;后者用 DEFAULTCAPACITY_EMPTY_ELEMENTDATA,首次 add 强制扩容为10,体现“懒加载默认容量”语义。

当指定容量为 0 时,ArrayList 的行为与无参构造有本质区别:它明确拒绝“懒加载默认容量”,直接进入空数组状态,后续扩容逻辑也不同。
指定 initialCapacity = 0 的构造行为
调用 new ArrayList(0) 时,源码会将 elementData 指向 EMPTY_ELEMENTDATA(一个长度为 0 的 final 空数组),此时:
- 数组长度固定为 0,不可写入任何元素
-
size仍为 0,但底层数组不具备“首次添加即扩到 10”的触发条件 - 第一次
add()会立即触发扩容,且新容量按需计算——不是默认 10,而是Math.max(10, minCapacity)中的minCapacity
与无参构造(new ArrayList())的关键差异
无参构造使用的是 DEFAULTCAPACITY_EMPTY_ELEMENTDATA,这是专为“懒初始化”设计的标记数组:
- 首次
add()时,calculateCapacity()识别出该标记,强制设新容量为DEFAULT_CAPACITY(即 10) - 而
EMPTY_ELEMENTDATA不具备该语义,扩容时走通用路径:oldCapacity + (oldCapacity >> 1),但 oldCapacity 是 0,所以 0 + 0 = 0 → 不满足需求 → 直接取minCapacity(即 1)→ 再经校验,最终扩为 10(因 JDK 规定最小扩容不低于 10)
实际扩容结果看似相同,但路径不同
虽然两种方式在第一次添加后都变成容量 10,但内部逻辑分叉明显:
立即学习“Java免费学习笔记(深入)”;
-
new ArrayList():靠标记数组 + 特殊判断,主动设为 10 -
new ArrayList(0):靠通用 grow() + 边界兜底(hugeCapacity()或Math.max(10, minCapacity)),被动升到 10 - 若后续再添加第 11 个元素,两者就完全一致:都从 10 扩到 15(10 + 10>>1)
为什么设计这种差异?
这是为了语义清晰:
- 无参构造表达“我接受默认行为”,框架可安全优化
- 显式传 0 表达“我明确要求零初始容量”,框架不擅自覆盖意图,仅保证功能可用
- 避免开发者误以为
new ArrayList(0)和new ArrayList()完全等价,实际在序列化、反射或调试时可能暴露底层数组引用不同


















