Kotlin二维数组属性返回引用致原数据被修改如何解决?
问题根因
Kotlin 中的数组属于引用类型,二维数组本质是「存储了一维数组引用」的数组。直接执行 val arr = c.someArray 时,仅复制了外层数组的内存引用,arr 和类内部的 someArray 指向堆内存中同一份数据,修改 arr 的元素本质就是在修改原始数组的内容,因此会出现原对象属性被同步改动的情况。
注意:如果直接调用数组的 clone() 或 copyOf() 方法处理二维数组,仅会完成浅拷贝——外层是新数组,但内层存储的一维数组依然是原对象的引用,修改内层元素还是会影响原始数据。
解决方法
要获取完全独立、修改不影响原属性的数组副本,需要对二维数组做深拷贝,有两种常见实现思路:
- 调用方获取数组时手动生成深拷贝
替换原测试代码中获取数组的逻辑,遍历每一层内层数组生成独立副本,再组装为新的二维数组:@Test fun test(){ val c = ClassHasArray() // 深拷贝:遍历每个内层BooleanArray生成副本,再组装为新的外层数组 val arr = c.someArray.map { it.clone() }.toTypedArray() arr[1][1] = true printArray(c.someArray) } - 类设计层面避免暴露内部数组引用
如果不希望任何外部调用方修改类内部的数组状态,可以把原始数组设为私有,公开属性每次访问时都返回深拷贝副本,从根源上杜绝外部拿到原始引用:class ClassHasArray { // 私有真实存储,外部无法直接访问 private val _someArray = Array(3) { BooleanArray(3) } // 公开属性每次返回深拷贝副本,外部修改不会影响内部数据 val someArray: Array<BooleanArray> get() = _someArray.map { it.clone() }.toTypedArray() }
验证结果
使用上述任意一种深拷贝方案后,测试代码的输出将符合预期,原始数组不会被修改:
[false, false, false] [false, false, false] [false, false, false]
提示:所有多维数组、存储引用类型元素的数组,要生成完全独立的副本都需要做逐层深拷贝,不能直接赋值或仅拷贝最外层。
内容的提问来源于stack exchange,提问作者user8637117
相关产品推荐
相关产品推荐

