Java 如何按值复制对象,而不是按引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2624165/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 10:01:52  来源:igfitidea点击:

How to copy an object by value, not by reference

java

提问by Blankman

I want to make a copy of an object, then after some logic, re-assign the original object the value of the copy.

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

example:

例子:

User userCopy = //make a copy

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

  UserDao.Update(user)


  user = userCopy; 

}

I don't want a copy by reference, it has to be a copy by value.

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

The above is just a sample, not how I really want to use it but I need to learn how to copy by value.

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

回答by Petar Minchev

Can't you just make a copy constructor? By the way Java always passes references by value, so you keep pointing to the same object.

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

回答by JC Ford

I believe .clone()is what you're looking for, so long as the class supports it.

我相信.clone()这就是你正在寻找的,只要班级支持它。

回答by KhanS

You need to do a deep copy from user to usercopy, and then after your login you can reassign your userCopy reference to user.

您需要从 user 到 usercopy 进行深层复制,然后在登录后您可以将 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;       
}

回答by Lie Ryan

what language is this? If you're using a language that passes everything by reference like Java (except for native types), typically you can call .clone()method. The .clone() method is typically implemented by copying/cloning all relevant instance fields into the new object.

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

回答by ewernli

Here are the few techniques I've heard of:

以下是我听说过的一些技巧:

  1. Use clone()if the class implements Cloneable. This API is a bit flawed in java and I never quite understood why cloneis not defined in the interface, but in Object. Still, it might work.

  2. Create a clone manually. If there is a constructor that accepts all parameters, it might be simple, e.g new User( user.ID, user.Age, ... ). You might even want a constructor that takes a User: new User( anotherUser ).

  3. Implement something to copy from/to a user. Instead of using a constructor, the class may have a method copy( User ). You can then first snapshot the object backupUser.copy( user )and then restore it user.copy( backupUser ). You might have a variant with methods named backup/restore/snapshot.

  4. Use the state pattern.

  5. Use serialization. If your object is a graph, it might be easier to serialize/deserialize it to get a clone.

  1. 使用clone()如果该类实现了Cloneable。这个 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. 使用状态模式

  5. 使用序列化。如果您的对象是图形,则序列化/反序列化它以获得克隆可能更容易。

That all depends on the use case. Go for the simplest.

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

EDIT

编辑

I also recommend to have a look at these questions:

我还建议看看这些问题:

回答by OscarRyz

You may use clone()which works well if your object has immutable objects and/or primitives, but it may be a little problematic when you don't have these ( such as collections ) for which you may need to perform a deep clone.

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

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

for(...) {
    user.age = 1;
    user.id = -1;

    UserDao.update(user)
    user = userCopy; 
}

It seems like you just want to preserve the attributes: ageand idwhich are of type intso, why don't you give it a try and see if it works.

好像你只是想保留的属性:ageid它们类型的int话,你为什么不给它一个尝试,看看它是否工作。

For more complex scenarios you could create a "copy" method:

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

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

It should take you about 10 minutes.

大约需要 10 分钟。

And then you can use that instead:

然后你可以改用它:

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

To read more about clone read this chapter in Joshua Bloch "Effective Java: Override clone judiciously"

要阅读有关克隆的更多信息,请阅读 Joshua Bloch “Effective Java: Override clone judiciously”中的这一章

回答by user2612526

I know this is a little bit too late but it might just help someone.

我知道这有点太晚了,但它可能只是帮助某人。

In my case I already had a method to make the Object from a json Object and make json from the object. with this you can simply create a new instance of the object and use it to restore. For instance in a function parsing a final object

就我而言,我已经有了一种方法可以从 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 
}