ArrayList扩容触发时机是添加前检查size+1 > elementData.length即扩,非固定“第11个”;新容量默认为原容量1.5倍(oldCapacity + oldCapacity>>1),不足minCapacity时直接取minCapacity;无参构造初始数组长度为0,首次add才扩容至10。

直接说重点:ArrayList 扩容不是“加了第11个元素才扩”,而是“添加前发现 size + 1 > elementData.length 就立刻扩”。这个判断逻辑,才是面试官想确认你是否真看过源码的分水岭。
扩容触发的真实时机
很多人背“默认容量10,第11个元素触发扩容”,这容易被反问:“那我 new ArrayList(0) 再 add(1),扩不扩?”——答案是扩,而且直接扩到 1。关键不在“第几个”,而在添加动作前的容量检查。
- 每次调用
add(E e),第一行就是ensureCapacityInternal(size + 1) - 它算的是“加完这个元素后,至少需要多少空间”,即最小需求容量(minCapacity)
- 只要
minCapacity > elementData.length,扩容立即发生,和当前 size 是 0 还是 99 无关
新容量怎么算?1.5 倍不是 magic number
核心代码就这一行:int newCapacity = oldCapacity + (oldCapacity >> 1)。右移 1 位等价于除以 2,所以是“原容量 + 一半”,也就是 1.5 倍。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 这不是随便定的:太小(如 1.1 倍)→ 扩容太频繁,复制开销大;太大(如 2 倍)→ 内存浪费严重
- 1.5 倍是工程权衡结果,在时间(复制成本)和空间(内存占用)之间取得较好平衡
- 注意:这是常规情况。如果计算出的 1.5 倍仍小于 minCapacity(比如初始为空数组却一次性 addAll 100 个),那就直接取 minCapacity,不硬套 1.5
初始容量的三个真相
所谓“默认容量是 10”,其实是个常见误解。准确说是:无参构造时数组长度为 0,首次 add 才升到 10。
立即学习“Java免费学习笔记(深入)”;
-
new ArrayList()→elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA(长度 0 的空数组) -
new ArrayList(5)→ 直接分配长度为 5 的数组 -
new ArrayList(list)→ 容量 =list.size()(若 list 非空)
Integer.MAX_VALUE - 8 是防什么?
源码里有常量 MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8。这不是拍脑袋减的 8,而是 JVM 对数组对象内存布局的要求:
- 数组在堆中是一个对象,除了元素数据,还有对象头(Header)、对齐填充等元信息
- JVM 规范要求数组长度字段必须能被安全表示,且留出空间给这些额外开销
- 减 8 是为兼容大多数 JVM 实现的内存模型,避免因溢出导致
OutOfMemoryError: Requested array size exceeds VM limit

















