Java中的对象拷贝指的是将一个对象的所有属性拷贝到另一个有着相同类型的对象中去。举例说明:比如,对象A和对象B都属于类S,具有属性a和b。那么对对象A进行拷贝操作赋值给对象B就是:B.a=A.a;B.b=A.b。Java中的对象拷贝主要分为:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。
浅拷贝
1、对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。2、对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。
省略get/set
/**
* 拷贝的对象
*
* @author : yangdehong
* @date : 2019/4/2 22:20
*/
public class CopyObject implements Cloneable {
private Integer age;
private String name;
private Long money;
public CopyObject() {
this.age = 11;
this.name = "央财";
this.money = 99L;
}
@Override
public String toString() {
return "CopyObject{" +
"age=" + age +
", name='" + name + '\'' +
", money=" + money +
'}';
}
// 重写Object类的clone方法
@Override
public Object clone() {
Object obj = null;
//调用Object类的clone方法,返回一个Object实例
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
}
/**
* 拷贝的对象
* @author : yangdehong
* @date : 2019/4/2 22:21
*/
public class ParentCopyObject implements Cloneable {
private CopyObject copyObject;
private String email;
private Integer high;
@Override
public String toString() {
return "ParentCopyObject{" +
"copyObject=" + copyObject +
", email='" + email + '\'' +
", high=" + high +
'}';
}
// 重写Object类的clone方法
@Override
public Object clone() {
Object obj = null;
//调用Object类的clone方法,返回一个Object实例
try {
obj = super.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return obj;
}
}
/**
* 浅拷贝
* @author : yangdehong
* @date : 2019/4/2 21:16
*/
public class ShallowCopyMain {
public static void main(String[] args) {
CopyObject copyObject = new CopyObject();
ParentCopyObject parentCopyObject = new ParentCopyObject();
parentCopyObject.setCopyObject(copyObject);
ParentCopyObject parentCopyObject2 = (ParentCopyObject) parentCopyObject.clone();
parentCopyObject2.getCopyObject().setAge(12);
parentCopyObject2.setEmail("123@qq.com");
System.out.println(parentCopyObject);
System.out.println(parentCopyObject2);
}
}
结果:copyObject的age两个都修改掉了;email只修改了自己
ParentCopyObject{copyObject=CopyObject{age=12, name='央财', money=99}, email='null', high=null}
ParentCopyObject{copyObject=CopyObject{age=12, name='央财', money=99}, email='123@qq.com', high=null}
深拷贝
对于深拷贝来说,不仅要复制对象的所有基本数据类型的成员变量值,还要为所有引用数据类型的成员变量申请存储空间,并复制每个引用数据类型成员变量所引用的对象,直到该对象可达的所有对象。也就是说,对象进行深拷贝要对整个对象图进行拷贝!
两个对象多实现implements Serializable
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* 深拷贝
* @author : yangdehong
* @date : 2019/4/2 23:00
*/
public class DeepCopyUtils {
@SuppressWarnings("unchecked")
public static <T> T copyObject(T src) {
T dest;
try {
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(byteOut);
out.writeObject(src);
ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream in = new ObjectInputStream(byteIn);
dest = (T) in.readObject();
} catch (Exception ex) {
ex.printStackTrace();
dest = null;
}
return dest;
}
}
public static void main(String[] args) {
// shallowCopy();
deepCopy();
}
public static void deepCopy() {
CopyObject copyObject = new CopyObject();
ParentCopyObject parentCopyObject = new ParentCopyObject();
parentCopyObject.setCopyObject(copyObject);
ParentCopyObject parentCopyObject2 = DeepCopyUtils.copyObject(parentCopyObject);
parentCopyObject2.getCopyObject().setAge(12);
parentCopyObject2.setEmail("123@qq.com");
System.out.println(parentCopyObject);
System.out.println(parentCopyObject2);
}
结果::copyObject的age只修改了自己;email只修改了自己
ParentCopyObject{copyObject=CopyObject{age=11, name='央财', money=99}, email='null', high=null}
ParentCopyObject{copyObject=CopyObject{age=12, name='央财', money=99}, email='123@qq.com', high=null}
其他方式
上面的浅拷贝是clone的方式,还可以通过构造函数的方式;深拷贝是通过序列化的方式,深拷贝还能通过clone的方式,这里就不详细说明了。