Java对象的深复制和浅复制详解

时间:2023-01-02 10:36:55

前言:

本文以实例介绍Java对象的深复制和浅复制使用对比。

浅复制:被复制的对象的所有变量都含有原来对象的相同值,对象中对其他对象的引用,仍指向原对象。
深复制:将引用对象的变量指向新对象,而不是原对象。

浅复制所复制的是对象的引用,对象的数据结构和数据都被复制,修改原对象也会对浅复制的对象也会发生同样的改变。如:Object a = b;即为浅复制。

深复制(克隆)所复制对象的数据结构,跟原对象不再有关联,修改原对象也不会对深复制对象产生影响。
如:Object a = b.clone();通过克隆深复制。

一.深复制的实现步骤

  1. 对象实现Cloneable接口(或Serializable接口)。
  2. 对象重写clone()方法。
  3. 调用object.clone()方法得到克隆对象。

实例

package com.deepcopy.demo;

//实现Cloneable接口
public class User implements Cloneable {
private String id;
private String name;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

//重写clone()方法
@Override
protected Object clone() throws CloneNotSupportedException {
User user = null;
user = (User) super.clone();
return user;
}
}

上述是一个标准的JavaBean对象,在此基础上实现了Cloneable接口,重写clone()方法,在此方法中将父类的克隆对象强制转换为User类即可。

注:强制转换最好加上try-catch捕获异常,为简洁展示,故此省略。
注:String 类型是拥有值类型特征的引用类型

二.深复制和浅复制的对比:

package com.deepcopy.demo;

public class DeepCopy {
private User user;//原对象
private User userClone;// 克隆对象
private User userCopy;// 浅复制对象

public static void main(String[] args) {
DeepCopy dCopy = new DeepCopy();
dCopy.test();
}

private void test() {
//实例化一个普通对象
user = new User();
user.setId("001");
user.setName("张三");
System.out.println("原对象user:" + user.getId()+","+user.getName());
//浅复制user对象
userCopy = user;

//克隆一份刚才的对象
try {
userClone = (User) user.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}

//改变原对象user的属性,观察浅复制对象和克隆对象的变化
user.setId("002");
user.setName("李四");

System.out.println("改变后的原对象user:" + user.getId()+","+user.getName());
System.out.println("浅复制对象userCopy:" + userCopy.getId()+","+userCopy.getName());
System.out.println("克隆对象userClone:" + userClone.getId()+","+userClone.getName());
}
}

输出结果:

原对象user:001,张三
改变后的原对象user:002,李四
浅复制对象userCopy:002,李四
克隆对象userClone:001,张三

从输出结果中可以看出,当原对象修改后,浅复制的对象也同样变化,但克隆对象(深复制)没有发生变化。

三.对象中包含其他JavaBean对象的克隆方法:

如果User中还包含其他的JavaBean对象时,仅通过上述的方法克隆后,该JavaBean对象不会被深复制。即修User对象内部的JavaBean对象的属性,克隆对象中的JavaBean对象也会发生变化,对对象中的对象是浅复制。

正确的做法:应该让内部JavaBean也实现ICloneable接口,并且重写clone()方法。然后在对其修改操作时,就不会影响克隆对象中的JavaBean对象了。若果第二层JavaBean对象中,还包含第三层,克隆方法同上,以此类推。

四.总结:

浅复制对象只是将复制原对象的引用地址,而克隆对象才会复制对象本身(数据结构),并与原对象断开关系。理解了对象的深复制,才能更好的理解设计模式的原型模式(点击查看)