You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

复用Map初始化对象时,对象变更同步引发Map异常变更的技术问题

问题原因与解决方案

这问题我之前在项目里也踩过坑!核心问题出在引用类型的传递机制上,咱们来拆解下你的代码到底发生了什么:

为什么修改Obj的List会同步改变Map的List?

Groovy里用map as Obj进行类型转换时,对于像List这种引用类型,并不会自动创建新的实例——它只是把Map里list对象的内存引用直接赋值给了Obj的list属性。也就是说,obj.list和map.list指向的是同一个ArrayList对象!不管你通过哪个变量去修改这个List,另一个变量看到的结果都会同步变化。

你的循环里每次调用obj.list.add(iterator),其实都是在给同一个List实例添加元素,所以最后Map的List和Obj的List内容完全一致,也就不奇怪了。

解决办法

有几种简单的方式可以避免这个问题,根据你的场景选就行:

1. 手动创建新List并复制原内容(最直接)

每次实例化Obj的时候,主动给list属性创建一个新的ArrayList,并把Map里的List内容复制进去:

def map = [ id: 0, list: [1,2] ]
class Obj {
    int id = 0
    List<Integer> list = new ArrayList<>()
}
for (iterator in 1..10){
    map.id = iterator
    // 手动初始化Obj的属性,给list创建新实例
    Obj obj = new Obj(
        id: map.id,
        list: new ArrayList<>(map.list)
    )
    obj.list.add(iterator)
    println "Obj.List: ${obj.list.toString()} Obj.id: ${obj.id}"
    println "map: ${map.list.toString()}"
}

2. 给Obj添加自定义构造方法(更优雅)

如果需要频繁从Map转换为Obj,可以给Obj加一个构造方法,自动处理引用类型的复制:

def map = [ id: 0, list: [1,2] ]
class Obj {
    int id = 0
    List<Integer> list = new ArrayList<>()

    // 接收Map参数的构造方法,自动复制List
    Obj(Map map) {
        this.id = map.id
        // 复制原List,空值时默认空List
        this.list = new ArrayList<>(map.list ?: [])
    }
}
for (iterator in 1..10){
    map.id = iterator
    Obj obj = new Obj(map)
    obj.list.add(iterator)
    println "Obj.List: ${obj.list.toString()} Obj.id: ${obj.id}"
    println "map: ${map.list.toString()}"
}

3. 使用克隆(适合临时场景)

利用ArrayList的clone()方法创建新实例(注意:这是浅克隆,适合元素是不可变类型如Integer的场景):

def map = [ id: 0, list: [1,2] ]
class Obj {
    int id = 0
    List<Integer> list = new ArrayList<>()
}
for (iterator in 1..10){
    map.id = iterator
    Obj obj = map as Obj
    // 克隆出一个新的List实例,切断引用
    obj.list = obj.list.clone()
    obj.list.add(iterator)
    println "Obj.List: ${obj.list.toString()} Obj.id: ${obj.id}"
    println "map: ${map.list.toString()}"
}

修改后的预期输出

最后一次迭代的输出会变成:

Obj.List: [1, 2, 10] Obj.id: 10
map: [1, 2]

这样Obj的修改就不会影响原Map的内容了!

内容的提问来源于stack exchange,提问作者Jacob Duncan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:50:14