arrays.copyof能实现防御性克隆,因其底层调用system.arraycopy创建全新数组对象,内存地址独立,返回新数组而非原引用,修改副本不影响原数组。

直接用 Arrays.copyOf 对敏感数组做浅拷贝,是防御性编程中最常用且有效的手段之一。它能确保外部代码无法通过引用修改内部状态,但需注意适用场景和潜在陷阱。
为什么 copyOf 能实现防御性克隆
Arrays.copyOf 底层调用 System.arraycopy,生成一个**全新数组对象**,内容与原数组相同但内存地址独立。原始数组和副本互不影响,从根本上切断了外部篡改内部数据的路径。
- 返回的是新数组,不是原数组引用
- 对副本的修改(如
arr[0] = x)不会影响原数组 - 适用于所有基本类型数组和对象数组(注意:对象数组中元素仍是引用)
正确用法:在 getter 和构造器中主动复制
敏感数组通常作为类的私有字段存在,必须在对外暴露时做隔离。关键位置包括:
- getter 方法:绝不直接返回私有数组引用
- 构造器参数:若接收外部传入的数组,应立即复制并保存副本
- setter 方法:赋值前先复制,避免后续被外部修改影响内部一致性
示例:
public class Account {private final String[] permissions;
public Account(String[] inputPermissions) {
// 防御性复制:防止调用方后续修改 inputPermissions
this.permissions = Arrays.copyOf(inputPermissions, inputPermissions.length);
}
public String[] getPermissions() {
// 返回副本,不暴露内部引用
return Arrays.copyOf(permissions, permissions.length);
}
}
对象数组要警惕“浅拷贝”局限
Arrays.copyOf 对对象数组只复制引用,不递归克隆元素本身。如果数组元素是可变对象(如 UserInfo),仍可能被间接修改。
- 若元素不可变(如
String,Integer),无需额外处理 - 若元素可变,需配合深拷贝逻辑:遍历副本并调用每个元素的克隆方法,或使用序列化/第三方库
- 更稳妥的做法是设计不可变元素,或改用
List<immutableclass></immutableclass>替代数组
避免常见误用
几个高频错误会削弱防御效果:
- 误用
Arrays.copyOf(array, 0)—— 返回空数组,但长度为 0,可能引发空指针或逻辑异常,应明确判断边界 - 忽略
null输入:调用前应校验参数是否为null,否则抛NullPointerException - 用错长度参数:如
Arrays.copyOf(arr, arr.length + 1)会补null或默认值,可能破坏业务语义 - 在循环或高频路径中无节制复制:虽安全但有开销,必要时可结合不可变包装(如
Collections.unmodifiableList)权衡
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











