【问题标题】:Copy Object Properties to a Map by Value not by Reference按值而不是按引用将对象属性复制到映射
【发布时间】:2014-09-08 17:08:10
【问题描述】:

我不确定我哪里出错了,但似乎我无法从对象实例复制属性并将它们分配给地图,而在保存实例后不更改值。

这是一个示例类:

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()

【问题讨论】:

    标签: grails groovy


    【解决方案1】:

    在不克隆的情况下,也可以通过“推”第一个来完成将 hash-map [:] 的值复制到新的 hash-map [:] 的空间,这将达到您想要的相同结果(按值复制)!

    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}"
    

    输出 ==>

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

    【讨论】:

      【解决方案2】:

      问题在于您实际上复制了对变量的引用。要获取变量的副本,您应该使用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] 
      

      【讨论】:

      • 我刚试了这段代码,稍作修改,我保存了productInstance.save(flush:true),并在保存前后打印出quantityOnHand,该值仍然被引用而不是复制。跨度>
      • 我将代码粘贴到我运行的问题中。我很惊讶将地图从一个地方复制到另一个地方是如此重要。至少,当我循环属性时,我应该能够将值复制到新地图而无需复制引用。
      • 好的,谢谢。但我不确定我是否得到你想要实现的行为。粘贴的代码将在调用save() 之前和之后打印10 - 不是吗?如果不是您在save() 之前和之后的预期?
      • 但是10是产品保存和修改之前的值,对吧? (修改保存后productInstance中的值为9)。
      • propertiesBefore.quantityOnHand 的值为10productInstance.quantityOnHand 的值为9。您在 save() 之前和之后打印了相同的值 (propertiesBefore.quantityOnHand)。
      【解决方案3】:

      一个更简单的使用 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}"
      

      输出 ==>

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

      【讨论】:

        猜你喜欢
        • 2011-02-07
        • 1970-01-01
        • 2019-04-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-10-27
        • 1970-01-01
        相关资源
        最近更新 更多