【问题标题】:How to copy an object by value, not by reference [duplicate]如何按值而不是按引用复制对象[重复]
【发布时间】:2011-02-07 03:00:49
【问题描述】:

我想制作一个对象的副本,然后经过一些逻辑,重新为原始对象分配副本的值。

示例:

User userCopy = //make a copy

foreach(...)
{
  user.Age = 1;
  user.ID = -1;

  UserDao.Update(user)


  user = userCopy; 

}

我不想要按引用复制,它必须是按值复制。

以上只是一个示例,并不是我真正想使用的方式,但我需要学习如何按值复制。

【问题讨论】:

    标签: java


    【解决方案1】:

    你不能只做一个复制构造函数吗?顺便说一句,Java 总是按值传递引用,所以你一直指向同一个对象。

    【讨论】:

    • 其实...Java 总是按值传递。只是,对于非基元来说,值是一个参考。
    • Java 不通过引用传递引用。 Java 按值传递引用。
    【解决方案2】:

    我相信.clone() 是您正在寻找的东西,只要该类支持它。

    【讨论】:

    • 咳咳。我们都知道克隆是邪恶的:)
    • 这不是邪恶的,只是被误解了。这意味着好。
    【解决方案3】:

    您需要从用户到用户副本进行深度复制,然后在登录后您可以将您的 userCopy 引用重新分配给用户。

    User userCopy = new User();
    userCopy.Age = user.Age
    userCopy.ID = user.ID
    
    foreach(...) 
    { 
      user.Age = 1; 
      user.ID = -1; 
    
      UserDao.Update(user)     
    
      user = userCopy;       
    }
    

    【讨论】:

      【解决方案4】:

      这是什么语言?如果您使用的语言通过引用传递所有内容,例如 Java(本机类型除外),通常可以调用 .clone() 方法。 .clone() 方法通常通过将所有相关实例字段复制/克隆到新对象中来实现。

      【讨论】:

        【解决方案5】:

        以下是我听说过的几种技术:

        1. 如果类实现了Cloneable,则使用clone()。这个API在java中有点缺陷,我一直不太明白为什么clone没有在接口中定义,而是在Object中。不过,它可能会起作用。

        2. 手动创建克隆。如果有一个接受所有参数的构造函数,它可能很简单,例如new User( user.ID, user.Age, ... )。你甚至可能想要一个带有用户的构造函数:new User( anotherUser ).

        3. 实现从/向用户复制的内容。该类可能有一个方法copy( User ),而不是使用构造函数。然后,您可以先对对象backupUser.copy( user ) 进行快照,然后再将其还原为user.copy( backupUser )。您可能有一个带有名为 backup/restore/snapshot 的方法的变体。

        4. 使用state pattern

        5. 使用serialization。如果你的对象是一个图,序列化/反序列化它可能更容易获得一个克隆。

        这一切都取决于用例。选择最简单的。

        编辑

        我还建议看看这些问题:

        【讨论】:

          【解决方案6】:

          如果您的对象具有不可变对象和/或原语,您可以使用clone(),它会很好地工作,但是当您没有可能需要执行的这些(例如集合)时,它可能会有点问题深度克隆。

          User userCopy = (User) user.clone();//make a copy
          
          for(...) {
              user.age = 1;
              user.id = -1;
          
              UserDao.update(user)
              user = userCopy; 
          }
          

          您似乎只想保留属性:ageid,它们的类型为 int,所以,您为什么不尝试一下,看看它是否有效。

          对于更复杂的场景,您可以创建“复制”方法:

          publc class User { 
              public static User copy( User other ) {
                   User newUser = new User();
                   newUser.age = other.age;
                   newUser.id = other.id;
                   //... etc. 
                   return newUser;
              }
          }
          

          大约需要 10 分钟。

          然后你可以使用它来代替:

               User userCopy = User.copy( user ); //make a copy
               // etc. 
          

          要了解有关克隆的更多信息,请阅读 Joshua Bloch "Effective Java: Override clone judiciously" 中的本章

          【讨论】:

            【解决方案7】:

            我知道这有点太晚了,但它可能会对某人有所帮助。

            在我的例子中,我已经有一种方法可以从 json 对象生成对象并从对象生成 json。有了这个,您可以简单地创建对象的新实例并使用它来恢复。例如在解析最终对象的函数中

            public void update(final Object object){ 
              final Object original = Object.makeFromJSON(object.toJSON()); 
              // the original is not affected by changes made to object 
            }

            【讨论】:

            • 这行得通..谢谢
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-10-27
            • 2017-03-15
            • 2017-09-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多