《Java 100 天进阶之路》第4篇:秒懂数组拷贝,感知新境界
第4篇:秒懂数组拷贝,感知新境界
📌 系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第3篇:为何要配置环境变量? |
➡️ 下一篇:第5篇:装箱和拆箱
一、核心知识点
- 数组拷贝的传统方式(循环赋值)及其低效问题
System.arraycopy()底层性能优势(JVM底层C/C++实现)Arrays.copyOf()便捷用法- 浅拷贝机制:引用复制 vs 对象新建
- 深拷贝的简单实现
二、通俗讲解(1分钟开心学)
1. 什么是数组拷贝?
假设你有一个装着5个球的箱子A(数组),你想把球全部复制到一个新箱子B(另一个数组)里。这就是数组拷贝。
2. 新手做法(循环逐个搬运)
for (int i = 0; i < src.length; i++) {
dest[i] = src[i];
}
没什么大问题,但如果箱子巨大(比如100万个球),每次搬一个,效率就低了。
3. 高手做法(直接撬动整排货架)
System.arraycopy() 是JVM底层用C/C++实现的,可以直接从内存中批量复制,就像用叉车一次性搬走整排货架,比手工搬快得多。
4. 浅拷贝是什么?
如果数组里放的不是基本类型(如int),而是对象(比如Person),那么拷贝的结果是:新数组里的元素和原数组里的元素指向内存中的同一批对象。你通过新数组修改了对象的属性,原数组对应对象的属性也会变。
生活类比:
你有一张同学录(原数组),上面写着张三家的地址。你复印了一份同学录(新数组),两份同学录上写的是同一个地址。你通过新同学录去张三家里涂鸦,原同学录上对应的张三也会被涂鸦覆盖。
三、实操代码案例 + 场景说明
场景:你需要将一个数组的部分元素复制到另一个数组的指定位置,例如在游戏开发中动态合并怪物列表。
1. 使用System.arraycopy()
// 源数组
int[] src = {10, 20, 30, 40, 50};
// 目标数组,长度比源数组大一点
int[] dest = new int[10];
// 参数:源数组,源起始索引,目标数组,目标起始索引,复制长度
System.arraycopy(src, 1, dest, 2, 3);
// dest变成: [0, 0, 20, 30, 40, 0, 0, 0, 0, 0]
2. 使用Arrays.copyOf()(更简洁)
int[] src = {1,2,3};
int[] newArr = Arrays.copyOf(src, 5); // 新数组长度5,多余元素补0
// newArr = [1,2,3,0,0]
3. 浅拷贝演示(引用类型数组)
class Person { String name; Person(String n) { name = n; } }
Person[] original = { new Person("张三"), new Person("李四") };
Person[] copy = Arrays.copyOf(original, original.length);
copy[0].name = "王五";
System.out.println(original[0].name); // 输出"王五" —— 原数组也被改了!
四、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
| 使用循环逐个拷贝对象数组后,以为修改副本不影响原数组 | 意外修改了原对象 | 理解浅拷贝,需要深拷贝时手动new新对象 |
System.arraycopy 源范围超出边界 |
IndexOutOfBoundsException |
确保源起始+长度 ≤ 源长度;目标起始+长度 ≤ 目标长度 |
认为Arrays.copyOf()能自动深拷贝 |
同上,还是浅拷贝 | 内存地址复制,不是对象复制 |
直接 int[] copy = original |
两个引用指向同一个数组,修改一个两个都变 | 使用copyOf或arraycopy创建新数组 |
五、面试高频考点
Q1:System.arraycopy() 和 Arrays.copyOf() 有什么区别?
System.arraycopy()需要提前创建好目标数组,可以指定起始位置;Arrays.copyOf()内部自动创建新数组(最终也调用了arraycopy),代码更简洁但灵活性稍弱。
Q2:什么是浅拷贝?什么情况下会出问题?
浅拷贝只复制对象的引用(地址),不复制对象本身。当通过副本修改对象内部状态时,原数组也会受影响。需要深拷贝时应遍历数组并逐个
new新对象或使用序列化。
Q3:如何实现一维对象数组的深拷贝?
简单方法:遍历原数组,对每个元素调用
clone()(如果对象实现了Cloneable)或手动new。更通用的方法:使用序列化(实现Serializable)后反序列化。
六、练习题
- 代码填空:
System.arraycopy(______, 0, ______, 0, 3);将源数组前3个元素复制到目标数组的前3个位置。 - 简答:浅拷贝在实际项目中可能导致什么bug?举例说明。
- 动手:写一个工具方法
public static <T> T[] deepCopy(T[] original),实现通用深拷贝(提示:利用序列化或new实例)。
📊 你的学习进度
- 当前:第4篇 / 共44篇 · 第一阶段:Java基础语法与环境
- ✅ 已完成:第1~3篇
- 📖 正在学:第4篇
- ⏳ 待学习:第5~44篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
💡 本专栏每篇都包含:避坑表 + 面试高频考点 + 练习题。每天30分钟,100天拿offer!
👉 下一篇文章预告
《装箱和拆箱》
内容简介:int 和 Integer 有什么区别?为什么 Integer 比较要用 equals?缓存池陷阱是怎么回事?
💡 学完这篇,你将彻底搞懂自动装箱拆箱的底层原理,面试再也不会被“128 == 128”绕晕。
📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!
更多推荐


所有评论(0)