自定义集合用Object[]实现扩容的关键是用elementData数组存对象、size记录有效长度、扩容时按1.5倍创建新数组并仅复制size个元素。所有操作必须严格基于size判断边界,确保不丢数据、不越界、不冗余。

在自定义集合类中用 Object[] 实现对象数组扩容,关键不是“怎么写 Object 类”,而是**如何用 Object 数组承载任意类型对象,并让扩容逻辑不丢数据、不越界、不冗余**。Java 中 Object 是所有类的父类,它本身不可实例化,但作为数组元素类型非常合适——这是泛型擦除前最底层的通用容器方式。
用 Object[] 做底层存储,必须明确三个字段职责
一个健壮的自定义集合(如简易 ArrayList)至少需维护:
-
elementData:真正存数据的
Object[],长度代表当前物理容量; - size:当前已存元素个数(有效长度),用于判断是否满、遍历范围、返回 size();
-
不维护冗余的 capacity 字段——容量就等于
elementData.length,避免同步错误。
错误做法是另设 int capacity 并手动更新;正确做法是直接读取 elementData.length,既准确又免维护。
扩容时机与判断逻辑要严格基于 size 和 length
扩容触发条件只有一个:添加新元素前,发现 size == elementData.length。不能用其他变量替代这个判断。
立即学习“Java免费学习笔记(深入)”;
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 例如:
if (size >= elementData.length)—— 安全,兼容边界; - 避免:
if (size == capacity)(capacity 若未及时更新就会失效); - 更不要:
if (size == initialSize * 2)(硬编码倍数,脱离实际数组状态)。
扩容操作三步不可少,且顺序不能错
每次扩容必须原子性完成以下三件事:
- 创建新数组:
Object[] newElementData = new Object[oldLength + (oldLength >> 1)](即 1.5 倍,与 ArrayList 一致); - 复制旧数据:
System.arraycopy(elementData, 0, newElementData, 0, size)—— 只拷贝size个有效元素,不是整个旧数组; - 切换引用:
elementData = newElementData,并确保后续所有操作都基于新数组。
注意:arraycopy 比 for 循环快,且不会因索引越界抛异常(只要参数合法);拷贝长度必须是 size,否则可能把 null 或残留值带进去,影响 toString() 或迭代逻辑。
增删查操作必须与 size 和 elementData 严格对齐
所有方法都要尊重 size 是“有效长度”这一事实:
-
add(E e):先判满扩容 → 再赋值elementData[size] = e→ 最后size++; -
get(int i):校验i < 0 || i >= size(不是>= elementData.length); -
toString():只遍历[0, size)范围,用Arrays.toString(Arrays.copyOf(elementData, size))最安全; -
remove(int i):移动时用arraycopy(elementData, i+1, elementData, i, size - i - 1),然后size--,末尾元素不置 null 也无妨(因 size 已减,对外不可见)。
这样写,无论存 String、Integer 还是自定义 Student 对象,都能统一处理,无需修改底层逻辑。

















