Java 你如何制作对象的深拷贝?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/64036/
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
How do you make a deep copy of an object?
提问by Andrei Savu
It's a bit difficult to implement a deep object copy function. What steps you take to ensure the original object and the cloned one share no reference?
实现深度对象复制功能有点困难。您采取了哪些步骤来确保原始对象和克隆对象不共享任何引用?
采纳答案by Jason Cohen
A safe way is to serialize the object, then deserialize. This ensures everything is a brand new reference.
一种安全的方法是序列化对象,然后反序列化。这确保一切都是全新的参考。
Here's an articleabout how to do this efficiently.
Caveats: It's possible for classes to override serialization such that new instances are notcreated, e.g. for singletons. Also this of course doesn't work if your classes aren't Serializable.
警告:类可以覆盖序列化,这样就不会创建新实例,例如单例。如果您的类不是可序列化的,这当然也不起作用。
回答by Orion Adrian
Deep copying can only be done with each class's consent. If you have control over the class hierarchy then you can implement the clonable interface and implement the Clone method. Otherwise doing a deep copy is impossible to do safely because the object may also be sharing non-data resources (e.g. database connections). In general however deep copying is considered bad practice in the Java environment and should be avoided via the appropriate design practices.
深度复制只能在每个班级同意的情况下进行。如果您可以控制类层次结构,那么您可以实现可克隆接口并实现 Clone 方法。否则不可能安全地进行深度复制,因为对象也可能共享非数据资源(例如数据库连接)。然而,一般而言,深复制在 Java 环境中被认为是不好的做法,应该通过适当的设计实践来避免。
回答by user8690
You can do a serialization-based deep clone using org.apache.commons.lang3.SerializationUtils.clone(T)
in Apache Commons Lang, but be careful—the performance is abysmal.
您可以org.apache.commons.lang3.SerializationUtils.clone(T)
在 Apache Commons Lang 中使用基于序列化的深度克隆,但要小心——性能非常糟糕。
In general, it is best practice to write your own clone methods for each class of an object in the object graph needing cloning.
通常,最好为需要克隆的对象图中的每个对象类编写自己的克隆方法。
回答by Adisesha
Use XStream(http://x-stream.github.io/). You can even control which properties you can ignore through annotations or explicitly specifying the property name to XStream class. Moreover you do not need to implement clonable interface.
使用 XStream( http://x-stream.github.io/)。您甚至可以通过注释或显式指定 XStream 类的属性名称来控制可以忽略哪些属性。此外,您不需要实现可克隆的接口。
回答by sankara
XStream is really useful in such instances. Here is a simple code to do cloning
XStream 在这种情况下非常有用。这是一个简单的代码来进行克隆
private static final XStream XSTREAM = new XStream();
...
Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));
回答by Julien Chastang
A few people have mentioned using or overriding Object.clone()
. Don't do it. Object.clone()
has some major problems, and its use is discouraged in most cases. Please see Item 11, from "Effective Java" by Joshua Bloch for a complete answer. I believe you can safely use Object.clone()
on primitive type arrays, but apart from that you need to be judicious about properly using and overriding clone.
一些人提到使用或覆盖Object.clone()
. 不要这样做。Object.clone()
有一些主要问题,在大多数情况下不鼓励使用它。请参阅Joshua Bloch 的“ Effective Java”中的第 11 条以获得完整的答案。我相信您可以安全地使用Object.clone()
原始类型数组,但除此之外,您需要明智地正确使用和覆盖克隆。
The schemes that rely on serialization (XML or otherwise) are kludgy.
依赖序列化(XML 或其他方式)的方案很笨拙。
There is no easy answer here. If you want to deep copy an object you will have to traverse the object graph and copy each child object explicitly via the object's copy constructor or a static factory method that in turn deep copies the child object. Immutables (e.g. String
s) do not need to be copied. As an aside, you should favor immutability for this reason.
这里没有简单的答案。如果要深度复制对象,则必须遍历对象图并通过对象的复制构造函数或静态工厂方法显式复制每个子对象,然后再深度复制子对象。不可变(例如String
s)不需要复制。顺便说一句,出于这个原因,您应该支持不变性。
回答by Julien Chastang
import com.thoughtworks.xstream.XStream;
public class deepCopy {
private static XStream xstream = new XStream();
//serialize with Xstream them deserialize ...
public static Object deepCopy(Object obj){
return xstream.fromXML(xstream.toXML(obj));
}
}
回答by Thargor
You can make a deep copy with serialization without creating files.
您可以在不创建文件的情况下使用序列化进行深度复制。
Your object you wish to deep copy will need to implement serializable
. If the class isn't final or can't be modified, extend the class and implement serializable.
您希望深度复制的对象将需要implement serializable
. 如果类不是 final 或无法修改,请扩展类并实现可序列化。
Convert your class to a stream of bytes:
将您的类转换为字节流:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(object);
oos.flush();
oos.close();
bos.close();
byte[] byteData = bos.toByteArray();
Restore your class from a stream of bytes:
从字节流中恢复您的类:
ByteArrayInputStream bais = new ByteArrayInputStream(byteData);
(Object) object = (Object) new ObjectInputStream(bais).readObject();
回答by Adriaan Koster
One way to implement deep copy is to add copy constructors to each associated class. A copy constructor takes an instance of 'this' as its single argument and copies all the values from it. Quite some work, but pretty straightforward and safe.
实现深度复制的一种方法是向每个关联的类添加复制构造函数。复制构造函数将 'this' 的一个实例作为其单个参数,并从中复制所有值。相当多的工作,但非常简单和安全。
EDIT: note that you don't need to use accessor methods to read fields. You can access all fields directly because the source instance is always of the same type as the instance with the copy constructor. Obvious but might be overlooked.
编辑:请注意,您不需要使用访问器方法来读取字段。您可以直接访问所有字段,因为源实例始终与具有复制构造函数的实例具有相同的类型。很明显,但可能会被忽略。
Example:
例子:
public class Order {
private long number;
public Order() {
}
/**
* Copy constructor
*/
public Order(Order source) {
number = source.number;
}
}
public class Customer {
private String name;
private List<Order> orders = new ArrayList<Order>();
public Customer() {
}
/**
* Copy constructor
*/
public Customer(Customer source) {
name = source.name;
for (Order sourceOrder : source.orders) {
orders.add(new Order(sourceOrder));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Edit: Note that when using copy constructors you need to know the runtime type of the object you are copying. With the above approach you cannot easily copy a mixed list (you might be able to do it with some reflection code).
编辑:请注意,在使用复制构造函数时,您需要知道要复制的对象的运行时类型。使用上述方法,您无法轻松复制混合列表(您可以使用一些反射代码来完成)。
回答by Ravi Chinoy
One very easy and simple approach is to use Hymanson JSON to serialize complex Java Object to JSON and read it back.
一种非常简单的方法是使用 Hymanson JSON 将复杂的 Java 对象序列化为 JSON 并将其读回。