system.arraycopy仅支持浅拷贝,深拷贝需配合手动创建新对象及逐层复制:多维数组须逐行新建并复制;对象数组需克隆元素;基本类型和string数组因不可变性可直接使用。

System.arraycopy 本身不能直接实现深拷贝,它只做浅拷贝——即复制数组元素的值(基本类型)或引用(对象/子数组),不递归复制被引用的对象内容。所谓“深拷贝技巧”,其实是用它作为高效搬运工具,配合手动逻辑完成真正的深拷贝。
下面分场景讲清楚怎么用、为什么这么用、以及关键避坑点:
多维数组的深拷贝:逐层用 arraycopy 搬数据
二维 int[][] 是最典型例子。arraycopy 可以高效复制每行的 int 元素,但必须自己分配新行数组:
int[][] src = {{1, 2, 3}, {4, 5}};
int[][] dst = new int[src.length][];
for (int i = 0; i <p>✅ 这样 <code>dst[0][0] = 99</code> 不会影响 <code>src[0][0]</code><br>
❌ 错误写法:<code>System.arraycopy(src, 0, dst, 0, src.length)</code> → 只复制了行引用,<code>dst[0] == src[0]</code></p><blockquote><p>注意:若子数组里存的是可变对象(如 <code>Person[]</code>),那 <code>arraycopy</code> 仍只复制引用,你还得对每个 <code>dst[i]</code> 再调 <code>clone()</code> 或构造新实例。</p></blockquote><h3>一维对象数组的深拷贝:先搬引用,再克隆元素</h3><p>假设 <code>Person</code> 正确实现了 <code>clone()</code>:</p><pre class="brush:java;toolbar:false;">Person[] src = {new Person("Alice"), new Person("Bob")};
Person[] dst = new Person[src.length];
System.arraycopy(src, 0, dst, 0, src.length); // 快速复制引用
for (int i = 0; i <p>⚠️ 如果 <code>Person</code> 没重写 <code>clone()</code>,或字段含可变对象(如 <code>List<address></address></code>),<code>clone()</code> 本身也只是浅拷贝,需进一步处理。</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2847" title="OpenJDK 24"><img
src="https://img.php.cn/upload/manual/001/431/639/6acf4227f079d889.png" alt="OpenJDK 24" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2847" title="OpenJDK 24" class="overflowclass">OpenJDK 24</a>
<p class="overflowclass">OpenJDK 24 Windows x64 官方参考实现(24+36),适合 Windows 环境进行 Java 开发、编译、运行和版本兼容性验证。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2847" title="OpenJDK 24" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div><h3>String[] 和基本类型数组:无需深拷贝,“伪深”即可用</h3>
-
int[]、double[]等:arraycopy复制的是数值,天然隔离,直接用。 -
String[]:虽然arraycopy复制的是引用,但String不可变,改dst[i] = "new"不影响src[i];即使dst[i].replace(...)也返回新对象,原引用不变。
所以这类数组用 arraycopy 就等于得到了行为上等价于深拷贝的效果。
深拷贝不是 arraycopy 的责任,而是你的设计责任
arraycopy 的角色是:
- 在已知结构的前提下,高速搬运连续内存块(比如一整行 int、一个 byte[] 片段)
- 它不识别“对象是否可变”,也不关心“子数组要不要新建”
真正决定是否深拷贝的,是你对数据语义的理解:
- 这个数组将来会不会被多处修改?
- 子元素是不是共享状态?
- 修改副本是否允许影响源头?
只要答案是“否”,你就得绕过 arraycopy 的浅层限制,主动创建新容器 + 用 arraycopy 填充底层数据。
不复杂但容易忽略
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










