我正在回顾Java的一些基本方面,并对浅克隆和深克隆有一些疑问。我很了解他们,并且了解内部原理。但是我偶然发现了这个简单的练习-
部门课-
public class Department {
String deptName;
public String getdName() {
return deptName;
}
public void setdName(String dName) {
this.deptName = dName;
}
public Department() {
super();
}
public Department(String dName) {
super();
this.deptName = dName;
}
}
员工阶层-
public class Employee implements Cloneable{
int empNo;
String empName;
Department dept;
public int getEmpNo() {
return empNo;
}
public void setEmpNo(int empNo) {
this.empNo = empNo;
}
public String getEmpName() {
return empName;
}
public void setEmpName(String empName) {
this.empName = empName;
}
public Department getDept() {
return dept;
}
public void setDept(Department dept) {
this.dept = dept;
}
public Employee(int empNo, String empName, Department dept) {
super();
this.empNo = empNo;
this.empName = empName;
this.dept = dept;
}
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
主类-
public class ShalowCopyTest {
public static void main(String args[]) {
Department dept1 = new Department("Development");
Department dept2 = new Department("Testing");
Employee emp1 = new Employee(10, "Peter", dept1);
Employee emp2 = null;
try {
emp2 = (Employee) emp1.clone();
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(emp1.getDept().getdName());
System.out.println(emp2.getDept().getdName());
System.out.println("Now changing emp1.dept");
//emp1.setDept(dept2); //This is deep cloning - why?
emp1.getDept().setdName("Testing"); //This is shallow cloning
System.out.println(emp1.getDept().getdName());
System.out.println(emp2.getDept().getdName());
}
}
您可以看到,如果我使用emp1.setDept(dept2),则更改emp1的dept对emp2无效。所以这是深克隆。但是仅通过emp1.getDept()。setdName(“ Testing”)更改dName也会使emp2的dName更改。所以这是浅克隆。为什么这两行会有所作为?为什么它们不一样?
谢谢。
最佳答案
我注意到您正在使用与此链接相同的示例:A Guide to Object Cloning in Java
可能您已经知道super.clone()的默认实现会执行“浅复制”而不是“深复制”。
在这种情况下,两个对象实例:emp1和emp2将包含指向内存中相同位置的引用。
引用Department实例,这是克隆emp1对象后在内存中的引用方式:
两者都指向内存中的同一位置,其中包含一个不变的字符串:“开发”。
通过设置:
emp1.setDept(dept2);
它将emp1的引用更改为新对象dept2:
在这种情况下,您会将其视为深度复制,但实际上并非如此。只是emp1更改了它对内存中新位置的引用。
在另一种情况下,设置时:
emp1.getDept().setdName("Testing");
您将Departman的名称更改为“ Testing”-对两个对象实例均可见。
如果您还有其他问题,请告诉我。