通过值而非参考将对象属性复制到地图

时间:2014-09-08 17:08:11

标签: grails groovy

我不知道自己哪里出错了,但似乎我无法从对象实例中复制属性并将其分配到地图而不会在保存后更改值实例。

这是一个示例类:

class Product {
    String productName
    String proudctDescription
    int quantityOnHand
}

提交表单并将其发送到我的控制器后,我可以访问这些值并从实例中提供的productInstance.properties地图中操作它们。我想将属性复制到另一个映射,以便在编辑期间提交它们之前保留这些值。因此,我们假设我们正在编辑记录,这些是存储在数据库中的值:productName = "My Product"productDescription = "My Product Description"quantityOnHand = 100

我想将它们复制到:

def propertiesBefore = productInstance.properties

这不起作用,因为当我保存productInstance时,propertiesBefore中的值会更改为实例所具有的值。

所以我尝试了这个:

productInstance.properties.each { k,v -> propertiesBefore[k] = v }

同样的事情又发生了。我不确定如何按值复制,似乎无论我尝试通过引用复制它而不是。

修改

根据Pawel P.的要求,这是我测试的代码:

class Product {
    String productName
    String productDescription
    int quantityOnHand
}

def productInstance = new Product(productName: "Some name", productDescription: "Desciption", quantityOnHand: 10)

def propertiesBefore = [:]
productInstance.properties.each { k,v -> propertiesBefore[k] = (v instanceof Cloneable) ? v.clone() : v }

productInstance.productName = "x"
productInstance.productDescription = "y"
productInstance.quantityOnHand = 9

println propertiesBefore.quantityOnHand // this will print the same as the one after the save() 
productInstance.save(flush:true)    
println propertiesBefore.quantityOnHand // this will print the same as the one above the save()

3 个答案:

答案 0 :(得分:3)

没有克隆,将hash-map [:]的值复制到新的hash-map [:]空间也可以通过" push"第一个结束,它将达到你想要的相同结果(按值复制)!

def APE = [:]
APE= [tail: 1, body: "hairy", hungry: "VERY!!!"]

def CAVEMAN = [:]
CAVEMAN << APE  //push APE to CAVEMAN's space

//modify APE's values for CAVEMAN
CAVEMAN.tail = 0
CAVEMAN.body = "need clothes"

println "'APE': ${APE}"
println "'CAVEMAN': ${CAVEMAN}"

输出==&gt;

'APE': [tail:1, body:hairy, hungry:VERY!!!]
'CAVEMAN': [tail:0, body:need clothes, hungry:VERY!!!]

答案 1 :(得分:1)

问题在于您实际上复制了对变量的引用。要获取变量副本,您应该使用clone()。看看:

class Product {
    String productName
    String productDescription
    int quantityOnHand
}

def productInstance = new Product(productName: "Some name", productDescription: "Desciption", quantityOnHand: 10)

def propertiesBefore = [:]
productInstance.properties.each { k,v -> propertiesBefore[k] = (v instanceof Cloneable) ? v.clone() : v }

productInstance.productName = "x"
productInstance.productDescription = "y"
productInstance.quantityOnHand = 9

println productInstance.properties
println propertiesBefore

打印:

[quantityOnHand:9, class:class Product, productName:x, productDescription:y]
[quantityOnHand:10, class:class Product, productName:Some name, productDescription:Desciption] 

答案 2 :(得分:1)

使用Hash-Map [:]的groovy的一个更简单的例子可以是这样的:

def APE = [:]
APE= [tail: 1, body: "hairy", hungry: "VERY!!!"]    

def CloneMe = APE  //*APE as clone*

def CAVEMAN = [:]    //*copy APE's values over thru mapping the clone*
CloneMe.each { key,value -> CAVEMAN[key] = (value instanceof Cloneable) ? value.clone() : value } 

println "'CloneMe': ${CloneMe}"

//change some of the clone's values for CAVEMAN
CAVEMAN.tail = 0
CAVEMAN.body = "need clothes"

println "'APE': ${APE}"
println "'CAVEMAN': ${CAVEMAN}"

输出==&gt;

'CloneMe': [tail:1, body:hairy, hungry:VERY!!!]
'APE': [tail:1, body:hairy, hungry:VERY!!!]
'CAVEMAN': [tail:0, body:need clothes, hungry:VERY!!!]