核心方法概览
| 方法 | 描述 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|---|
System.arraycopy() |
性能最高的底层方法,用于在数组之间复制数据。 | 速度极快,是所有方法中最优的。 | 语法稍显冗长,需要指定源数组、起始位置、目标数组、起始位置和长度。 | 性能要求极高的场景,如大文件处理、高频网络通信等。 |
Arrays.copyOf() |
java.util.Arrays 提供的工具方法,可以复制数组并可选择性地调整新数组长度。 |
语法简洁,代码可读性好。 | 内部实现也是 System.arraycopy(),性能同样优秀。 |
大多数日常开发场景,推荐首选。 |
Arrays.copyOfRange() |
java.util.Arrays 提供的工具方法,用于复制数组的一个子集。 |
语法简洁,专门用于复制指定范围。 | 性能同 copyOf()。 |
当你只需要复制数组的一部分时,非常方便。 |
| 手动循环复制 | 使用 for 循环或 for-each 循环逐个元素复制。 |
灵活性高,逻辑直观,适合初学者理解。 | 性能最差,代码冗长,容易出错。 | 仅用于学习目的,或需要在复制过程中对每个元素进行特殊处理时。 |
ByteBuffer |
使用 NIO (java.nio.ByteBuffer) 进行复制。 |
功能强大,可以与 NIO 的其他组件(如通道)无缝集成。 | 对于简单的数组复制,显得有些“重”,代码量稍多。 | 在 NIO 网络编程或文件 I/O 场景中,需要将字节数组与缓冲区互转时。 |
详细代码示例
假设我们有以下原始数组:

byte[] srcArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
System.arraycopy() - 性能之王
这是最底层、最高效的方法,它直接在内存块之间进行数据拷贝。
byte[] srcArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 创建一个和源数组一样大的目标数组
byte[] destArray = new byte[srcArray.length];
// 调用 System.arraycopy
// 参数: 源数组, 源起始索引, 目标数组, 目标起始索引, 复制长度
System.arraycopy(srcArray, 0, destArray, 0, srcArray.length);
// 验证结果
System.out.println(Arrays.toString(destArray)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
特点:
- 性能:毋庸置疑,这是最快的。
- 灵活性:可以指定源数组和目标数组的任意起始位置,以及任意长度。
- 注意:如果目标数组长度不够,会抛出
ArrayIndexOutOfBoundsException。
Arrays.copyOf() - 简洁首选
这是 java.util.Arrays 类提供的一个便捷方法,非常常用。
import java.util.Arrays;
byte[] srcArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 创建一个新数组,其内容是 srcArray 的副本,长度与 srcArray 相同
byte[] destArray = Arrays.copyOf(srcArray, srcArray.length);
// 验证结果
System.out.println(Arrays.toString(destArray)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
特点:

-
简洁性:一行代码搞定,非常清晰。
-
长度灵活性:如果新长度大于原数组,多余的元素会被填充为
0(byte 的默认值),如果新长度小于原数组,则只复制前面的元素。// 复制前 5 个元素 byte[] shortCopy = Arrays.copyOf(srcArray, 5); System.out.println(Arrays.toString(shortCopy)); // 输出: [1, 2, 3, 4, 5] // 复制并填充 0 byte[] longCopy = Arrays.copyOf(srcArray, 15); System.out.println(Arrays.toString(longCopy)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0]
-
性能:其内部实现就是
System.arraycopy(),所以性能和System.arraycopy()一样好。
Arrays.copyOfRange() - 精准截取
当你需要复制数组的一部分时,这个方法非常方便。
import java.util.Arrays;
byte[] srcArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 复制从索引 2 (包含) 到索引 6 (不包含) 的元素
byte[] subArray = Arrays.copyOfRange(srcArray, 2, 6);
// 验证结果
System.out.println(Arrays.toString(subArray)); // 输出: [3, 4, 5, 6]
特点:
- 精准性:专门用于复制一个子数组,左闭右开区间
[from, to)。 - 长度自动计算:新数组的长度是
to - from,无需手动计算。 - 性能:同样基于
System.arraycopy(),性能优秀。
手动循环复制 - 不推荐用于生产
这种方式最原始,不推荐在实际项目中使用,除非有特殊需求。
import java.util.Arrays;
byte[] srcArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
byte[] destArray = new byte[srcArray.length];
// 使用 for 循环
for (int i = 0; i < srcArray.length; i++) {
destArray[i] = srcArray[i];
}
// 验证结果
System.out.println(Arrays.toString(destArray)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
特点:
- 性能差:循环有开销,逐个赋值比内存块拷贝慢得多。
- 代码冗长:需要手动管理索引,容易出错。
- 适用性:仅用于教学,或者在循环中需要对每个元素进行复杂逻辑处理时。
ByteBuffer - NIO 场景下的选择
在处理网络或文件 I/O 时,ByteBuffer 是一个核心类,它提供了复制 byte 数组的方法。
import java.nio.ByteBuffer;
import java.util.Arrays;
byte[] srcArray = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 1. 将 byte 数组包装到 ByteBuffer 中
ByteBuffer srcBuffer = ByteBuffer.wrap(srcArray);
// 2. 创建一个新的 ByteBuffer,容量相同
ByteBuffer destBuffer = ByteBuffer.allocate(srcBuffer.capacity());
// 3. 将 srcBuffer 的内容复制到 destBuffer
// 注意:这会复制 srcBuffer 的当前位置到末尾的所有数据
// srcBuffer 的 position 不为 0,可能需要先重置
srcBuffer.rewind(); // 将 position 设置为 0
destBuffer.put(srcBuffer);
// 4. 从 ByteBuffer 中获取字节数组
byte[] destArray = destBuffer.array();
// 验证结果
System.out.println(Arrays.toString(destArray)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
特点:
- NIO 集成:在 NIO 生态中非常方便,可以直接用于
SocketChannel或FileChannel。 - 功能丰富:
ByteBuffer提供了缓冲区的概念(position, limit, capacity),功能比单纯的数组强大。 - “重量级”:对于简单的数组复制,创建
ByteBuffer对象的开销比前几种方法大。
总结与最佳实践
| 场景 | 推荐方法 | 理由 |
|---|---|---|
| 通用、日常开发 | Arrays.copyOf() |
代码简洁、可读性好,性能卓越,是首选。 |
| 需要复制数组的一部分 | Arrays.copyOfRange() |
语法清晰,专为子数组复制设计。 |
| 性能要求极致 | System.arraycopy() |
底层最快,但代码稍显复杂,在性能瓶颈分析时可以考虑。 |
| NIO 编程 | ByteBuffer |
与 NIO 管道和通道无缝对接,是 NIO 生态的标准做法。 |
| 学习或特殊处理 | 手动循环 | 便于理解复制过程,或需要在复制时对每个元素进行额外操作。 |
最终建议:
在 99% 的情况下,直接使用
Arrays.copyOf()或Arrays.copyOfRange()是最佳选择,它们提供了最佳的性能和代码可读性的平衡。
