
本文详解 java 中手动实现动态数组扩容的核心要点,包括正确更新容量变量、避免越界访问、修复遍历逻辑等关键问题,并提供可直接运行的完整示例代码。
在 Java 中,原生数组(如 int[])是固定长度的,无法直接“改变大小”。但我们可以模拟动态数组行为——当元素数量超出当前容量时,创建一个更大的新数组,将旧数据复制过去,并更新引用。这正是 ArrayList 底层的核心机制。然而,手动实现时极易忽略关键细节,导致扩容失效或逻辑错误。
? 常见错误分析
你提供的 Array 类中存在两个关键缺陷:
size 字段未同步更新
resize() 方法中创建了新数组 new int[size * 2],但扩容后未更新 this.size。结果:后续调用 isFull() 仍基于原始 size(如 5),而 array.length 已变为 10 —— 两者脱节,isFull() 判断失效,导致下一次添加时可能越界。print() 方法遍历逻辑错误
当前使用 for (int i = 0; i
✅ 正确实现方案
以下是修复后的完整代码(关键修改已加注释):
网页中拖动 DIV 是很常见的操作,今天就分享给大家一个 jQuery 多列网格拖动布局插件,和其它的插件不太一样的地方在于你处理拖放的元素支持不同大小,并且支持多列的网格布局,它们会自动的根据位置自己排序和调整。非常适合你开发具有创意的应用。这个插件可以帮助你将任何的 HTML 元素转换为网格组件
立即学习“Java免费学习笔记(深入)”;
public class Array {
private int[] array;
private int pointer; // 当前已存储元素个数(即下一个插入位置)
public Array() {
this(5);
}
public Array(int initialCapacity) {
if (initialCapacity < 0) throw new IllegalArgumentException("Capacity must be non-negative");
this.array = new int[initialCapacity];
this.pointer = 0;
}
public void add(int element) {
if (pointer == array.length) { // 使用 array.length 替代 isFull(),更简洁可靠
resize();
}
array[pointer++] = element;
}
private void resize() {
int newSize = array.length * 2;
if (newSize == 0) newSize = 1; // 防止初始容量为0时死循环
int[] temp = new int[newSize];
System.arraycopy(array, 0, temp, 0, array.length); // 推荐使用系统级拷贝,高效安全
array = temp;
// 注意:无需维护独立的 size 字段!array.length 即当前容量
}
public void print() {
for (int i = 0; i < pointer; i++) { // 仅打印已添加的元素
System.out.println(array[i]);
}
}
public int size() {
return pointer; // 返回逻辑大小(元素个数)
}
public boolean isEmpty() {
return pointer == 0;
}
}⚠️ 关键注意事项
- 移除冗余字段:size 字段完全多余。Java 数组的 .length 属性天然反映当前容量,应直接使用 array.length 进行容量判断和分配。
- 使用 System.arraycopy:比手动 for 循环拷贝更高效、更安全(尤其对大数组),且能处理 null 和边界校验。
- pointer 是核心状态变量:它既是已存元素数量,也是下一个插入索引,务必在每次 add() 后自增。
- 边界防护:resize() 中增加 if (newSize == 0) newSize = 1,避免初始容量为 0 导致无限扩容(虽然本例默认为 5,但增强鲁棒性)。
- 命名语义化:将 size 字段重命名为 pointer(或更准确的 size 表示逻辑大小),避免与容量(capacity)混淆。当前代码中 pointer 更贴合其作用。
? 测试验证
public static void main(String[] args) {
Array arr = new Array(2); // 初始容量为2
arr.add(10);
arr.add(20);
arr.add(30); // 触发 resize → 容量变为4
arr.add(40);
arr.add(50); // 再次 resize → 容量变为8
arr.print(); // 输出:10, 20, 30, 40, 50(无多余0)
System.out.println("Actual size: " + arr.size()); // 输出:5
}通过以上修正,你的自定义 Array 类即可稳定支持动态扩容,行为与 ArrayList 的核心逻辑一致。掌握这一机制,不仅有助于理解集合框架底层原理,也是面试中高频考察的手写数据结构能力点。









