使用映射初始化对象

时间:2018-05-31 18:37:12

标签: groovy

我无法重复使用地图来创建新对象。地图随对象一起变化:

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
    obj.list.add(iterator)
    println ("Obj.List: ${obj.list.toString()} \nObj.id: ${obj.id}")
    println "map: ${map.list.toString()}"
}

最后一次迭代的输出:

1. Obj.List: [1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

2. map: [1, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

1 个答案:

答案 0 :(得分:0)

它发生在您身上,因为您面临传递对列表的引用而不是创建其副本。 Groovy默认添加了map构造函数,对于类Obj,这个构造函数实际上与:

相同
class Obj {
    int id = 0
    List<Integer> list = new ArrayList<>()

    Obj(Map map) {
        id = map.id
        list = map.list
    }
}

作业list = map.list表示obj.listmap.list引用内存中的同一个对象,这就是为什么当您向obj.list添加内容时,它也可用当您访问map.list时。至少有两种方法可以解决它。

1。在Obj class

中实现自己的构造函数

在这种情况下,请确保obj.list获得自己的新名单,例如

class Obj {
    int id = 0
    List<Integer> list = new ArrayList<>()

    Obj(Map map) {
        id = map.id
        list = map.list.clone()
    }
}

2。创建对象后用副本覆盖map.list

在某些情况下,您可能希望保持默认构造函数不变。在这种情况下,您可以简单地使用列表的新副本覆盖map.list,例如

for (iterator in 1..10){
    map.id = iterator
    Obj obj = map as Obj
    obj.list = map.list.clone()
    obj.list.add(iterator)
    println ("Obj.List: ${obj.list.toString()} \nObj.id: ${obj.id}")
    println "map: ${map.list.toString()}"
}

应用的两个选项产生以下控制台输出:

Obj.List: [1, 2, 1] 
Obj.id: 1
map: [1, 2]
Obj.List: [1, 2, 2] 
Obj.id: 2
map: [1, 2]
Obj.List: [1, 2, 3] 
Obj.id: 3
map: [1, 2]
Obj.List: [1, 2, 4] 
Obj.id: 4
map: [1, 2]
Obj.List: [1, 2, 5] 
Obj.id: 5
map: [1, 2]
Obj.List: [1, 2, 6] 
Obj.id: 6
map: [1, 2]
Obj.List: [1, 2, 7] 
Obj.id: 7
map: [1, 2]
Obj.List: [1, 2, 8] 
Obj.id: 8
map: [1, 2]
Obj.List: [1, 2, 9] 
Obj.id: 9
map: [1, 2]
Obj.List: [1, 2, 10] 
Obj.id: 10
map: [1, 2]