实现深度对象复制函数有点困难。您采取什么步骤来确保原始对象和克隆对象没有共享引用?
当前回答
深度复制只能在每个班级同意的情况下进行。如果您可以控制类层次结构,那么您可以实现可克隆接口并实现Clone方法。否则进行深度复制是不可能安全的,因为对象也可能共享非数据资源(例如数据库连接)。一般来说,深度复制在Java环境中被认为是不好的做法,应该通过适当的设计实践来避免。
其他回答
使用Jackson序列化和反序列化对象。此实现不需要对象实现Serializable类。
<T> T clone(T object, Class<T> clazzType) throws IOException {
final ObjectMapper objMapper = new ObjectMapper();
String jsonStr= objMapper.writeValueAsString(object);
return objMapper.readValue(jsonStr, clazzType);
}
1)
public static Object deepClone(Object object) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(object);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
}
catch (Exception e) {
e.printStackTrace();
return null;
}
}
2)
// (1) create a MyPerson object named Al
MyAddress address = new MyAddress("Vishrantwadi ", "Pune", "India");
MyPerson al = new MyPerson("Al", "Arun", address);
// (2) make a deep clone of Al
MyPerson neighbor = (MyPerson)deepClone(al);
这里,您的MyPerson和MyAddress类必须实现可序列化接口
实现深度复制的一种方法是向每个相关类添加复制构造函数。复制构造函数将'this'的实例作为其单个参数,并从该实例复制所有值。工作量很大,但很简单也很安全。
编辑:请注意,您不需要使用访问器方法来读取字段。您可以直接访问所有字段,因为源实例总是与具有复制构造函数的实例具有相同的类型。显而易见,但可能会被忽视。
例子:
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;
}
}
编辑:注意,复制构造函数不考虑继承。例如:如果您将OnlineOrder (Order的子类)传递给一个复制构造函数,则将在副本中创建一个常规的Order实例,除非您显式地解决这个问题。可以使用反射在实参的运行时类型中查找复制构造函数。但是我建议不要走这条路,如果需要以一般的方式讨论继承,就寻找另一种解决方案。
一些人提到了使用或重写Object.clone()。不要这样做。Object.clone()存在一些主要问题,在大多数情况下不鼓励使用它。请参见Joshua Bloch的“Effective Java”中的第11项,以获得完整的答案。我相信您可以安全地在基本类型数组上使用Object.clone(),但除此之外,您还需要明智地正确使用和重写clone。
依赖于序列化(XML或其他方式)的方案是拙劣的。
这个问题没有简单的答案。如果你想要深度复制一个对象,你必须遍历对象图,并通过对象的复制构造函数或静态工厂方法显式复制每个子对象,然后再深度复制子对象。不需要复制不可变对象(例如字符串)。顺便说一句,出于这个原因,您应该支持不可变性。
XStream在这种情况下非常有用。这是一个简单的代码来做克隆
private static final XStream XSTREAM = new XStream();
...
Object newObject = XSTREAM.fromXML(XSTREAM.toXML(obj));
推荐文章
- 如何格式化Joda-Time DateTime仅为mm/dd/yyyy?
- 如何在POM.xml中引用环境变量?
- 如何在android中复制一个文件?
- 将整数转换为字符串,以逗号表示千
- 接口方法的最终参数-有什么意义?
- Java中的@UniqueConstraint注释
- 如何在清洁模式下运行eclipse ?如果我们这样做会发生什么?
- 获取java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory异常
- Java中的正则表达式命名组
- c#和Java的主要区别是什么?
- 什么是NullPointerException,我如何修复它?
- 在Java中使用“final”修饰符
- 无法在Flutter上找到捆绑的Java版本
- 如何在Kotlin解析JSON ?
- 如何在新的材质主题中改变背面箭头的颜色?