arrays.copyof 以 newlength 为准创建新数组,不自动修正长度:newlength > 原长则填充默认值,= 则等长拷贝,
Arrays.copyOf 是 Java 中最常用的数组拷贝工具之一,它看似简单,但内部实现细节和边界处理稍有不慎就容易引发
ArrayIndexOutOfBoundsException或静默截断/填充问题。它的核心不是直接调用System.arraycopy就完事,而是有一套明确的长度校验、类型推导与新数组构造逻辑。copyOf 如何决定新数组长度与类型
该方法本质是泛型桥接方法,最终委托给
Object[]版本或基本类型专用重载(如copyOf(int[], int))。关键点在于:它严格以第二个参数newLength为准创建新数组,不参考原数组长度做自动修正。
- 若
newLength > original.length:新数组扩容,多出位置用默认值填充(null、0、false等)- 若
newLength == original.length:等长拷贝,等价于深拷贝(仅一层引用)- 若
0 :截断拷贝,只复制前 <code>newLength个元素- 若
newLength :直接抛 <code>NegativeArraySizeException(在分配新数组前就失败)底层调用 System.arraycopy 的安全边界
copyOf在完成新数组创建后,会调用System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength))。注意这个Math.min—— 它是防止越界的真正守门员。
- 即使你传入
newLength = 1000但原数组只有 5 个元素,也只会拷贝 5 个,不会越界- 如果原数组为
null,copyOf会立即抛NullPointerException(不等到arraycopy阶段)System.arraycopy本身不校验源数组是否为空,但copyOf提前做了防御性检查实战中容易踩的坑与规避方式
日常开发中,开发者常把
copyOf当作“安全版arraycopy”,却忽略其行为隐含语义:
- 不要依赖原数组长度做逻辑判断后再调用 copyOf:比如先写
if (arr.length > 10) doX();,再Arrays.copyOf(arr, 10)——若arr为空,doX()不执行,但copyOf仍会返回长度为 10 的全零数组,可能破坏后续流程- 泛型数组拷贝需注意类型擦除限制:对
List<string>[]</string>这类嵌套泛型数组,copyOf返回的是Object[],强转可能触发ClassCastException- 大数据量场景慎用无脑扩容:如循环中反复
copyOf(arr, arr.length + 1)模拟动态数组,时间复杂度退化为 O(n²),应改用ArrayList替代方案与何时该换用其他机制
当需求超出
copyOf的能力边界时,可考虑:它不复杂,但容易忽略边界语义。理解
- 需要浅拷贝+过滤:用
Stream.of(arr).filter(...).toArray()- 需要深拷贝对象数组:手动遍历并调用
clone()或序列化工具- 需要偏移拷贝(非从 0 开始):直接用
System.arraycopy(original, fromIndex, copy, 0, length)- 需要不可变视图:用
Arrays.asList(arr).unmodifiableList()(注意底层数组仍可变)newLength是唯一长度指令、原数组只提供数据源,就能避开绝大多数误用。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南












