Java | 深拷贝与浅拷贝
程序员文章站
2022-05-28 14:33:16
...
Java中有三种类型的对象拷贝:
深拷贝(Deep Copy)、浅拷贝(Shallow Copy)、延迟拷贝(Lazy Copy)
深拷贝
深度拷贝将拷贝遇到的每个对象。副本和原始对象不会共享任何东西,所以它将是原件的副本。
深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。
深拷贝相比于浅拷贝速度较慢并且花销较大。
图示标注:深拷贝的情况下,在 SourceObject 中改变其中的引用对象 refObj ,不会影响 CopiedObject 的结果,反之亦然
浅拷贝
浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。
浅层复制将复制*属性,但是嵌套对象将在原始(源)对象和副本(目标)对象之间是共享。
图示标注:浅拷贝的情况下,在 SourceObject 中改变其中的引用对象 refObj ,会影响 CopiedObject 的结果
refObj
public class Subject {
private String name;
public Subject(String s) {
name = s;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
}
SourceObj-浅拷贝/深拷贝
public class Student implements Cloneable {
// 对象引用
private Subject subj;
private String name;
public Student(String s, String sub) {
name = s;
subj = new Subject(sub);
}
public Subject getSubj() {
return subj;
}
public String getName() {
return name;
}
public void setName(String s) {
name = s;
}
public Object clone() {
//浅拷贝
try {
// 直接调用父类的clone()方法
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
// 深拷贝,创建拷贝类的一个新对象,这样就和原始对象相互独立
//Student s = new Student(name, subj.getName());
//return s;
}
}
测试文件
public class CopyTest {
public static void main(String[] args) {
// 原始对象
Student stud = new Student("John", "Algebra");
System.out.println("Original Object: " + stud.getName() + " - " + stud.getSubj().getName());
// 拷贝对象
Student clonedStud = (Student) stud.clone();
System.out.println("Cloned Object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName());
// 原始对象和拷贝对象是否一样:
System.out.println("Is Original Object the same with Cloned Object: " + (stud == clonedStud));
// 原始对象和拷贝对象的name属性是否一样
System.out.println("Is Original Object's field name the same with Cloned Object: " + (stud.getName() == clonedStud.getName()));
// 原始对象和拷贝对象的subj属性是否一样
System.out.println("Is Original Object's field subj the same with Cloned Object: " + (stud.getSubj() == clonedStud.getSubj()));
stud.setName("Dan");
stud.getSubj().setName("Physics");
System.out.println("Original Object after it is updated: " + stud.getName() + " - " + stud.getSubj().getName());
System.out.println("Cloned Object after updating original object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName());
}
}