如何按值而不是按引用复制对象[重复]

Posted

技术标签:

【中文标题】如何按值而不是按引用复制对象[重复]【英文标题】: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; 


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

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

【问题讨论】:

【参考方案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】:

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

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

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

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

    使用state pattern。

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

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

编辑

我还建议看看这些问题:

Clone() vs. Copy constructor How to properly override clone method

【讨论】:

【参考方案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 

【讨论】:

这行得通..谢谢

以上是关于如何按值而不是按引用复制对象[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在 Python 2 中,无论列表的内容如何,​​如何按值而不是引用复制复杂嵌套元素的列表

Java 对象复制的最佳选择? [复制]

如何按值而不是按引用将数组添加到列表中?

如何在java中深度复制对象。该对象可能是也可能不是可序列化的[重复]

Ruby 是按值传递还是按引用传递? [复制]

在 lambda 中,引用的按值捕获是不是会复制底层对象?