本文针对 Java ArrayList 源码中的三个常见疑问展开分析:

1. 减法比较 vs 直接比较

grow() 方法中使用 newCapacity - MAX_ARRAY_SIZE > 0 而非直接比较,是为了处理整数溢出的极端情况。

  • 直接比较 :若 newCapacity 溢出为负数(如扩容过大),会错误跳过容量校验逻辑。
  • 减法比较 :溢出后的结果可能触发 hugeCapacity() 方法,通过检查 minCapacity 是否溢出(负数)抛出 OutOfMemoryError,确保异常情况被捕获。

2. MAX_ARRAY_SIZE 设为 Integer.MAX_VALUE - 8 的原因

  • 预留元数据空间 :避免因 JVM 对象头(类型指针、数组长度等)占用内存导致分配失败。
  • 兼容性保障 :不同 JVM 实现可能对数组元数据有不同要求,预留 8 字节增强通用性。
  • 极端突破机制hugeCapacity() 方法仍允许在安全条件下分配至 Integer.MAX_VALUE,平衡安全性与灵活性。

3. modCount 的作用与 Fail-Fast 机制

  • 功能 :记录集合结构性修改次数(如增删元素),用于迭代时检测并发修改。
  • 实现原理 :迭代器保存初始 expectedModCount,每次操作前校验与 modCount 是否一致,不一致则抛出 ConcurrentModificationException
  • 应用场景 :防止单线程迭代时误改集合,或暴露多线程并发修改问题,辅助开发者快速定位逻辑错误。

核心总结 :通过源码级分析,揭示了 ArrayList 在容量计算、内存分配安全边界及并发修改检测中的设计权衡,体现了 Java 集合框架对稳定性、兼容性和异常处理的细致考量。