【发布时间】:2016-08-31 07:12:54
【问题描述】:
我正在重新审视 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。所以这是浅层克隆。为什么这两条线会有所作为?为什么他们不一样? 谢谢。
【问题讨论】:
-
您在这里比较苹果和橘子。两条线都应该导致某些东西“粘住”。在第一种情况下,您更新了部门,在第二种情况下,您更新了名称。
-
嗨@TimBiegeleisen,谢谢!问题是如果我直接更改原始部门的名称,那么原始参考会被更新。在这种情况下,它不会创建另一个副本并在那里进行更改,它只是更新原始副本,这会影响 emp1 和 emp2。但是,如果我将部门作为一个整体进行更改,那么它将制作部门的另一个副本并将其分配给克隆。那么为什么在这种情况下它会创建另一个部门参考?代码的哪一部分告诉这样做?如果你看到 setDept() 方法,我使用的是 this.dept=dept -> 表示浅克隆!
-
我没有使用 new() 来创建一个新的部门,然后再修改它!我也没有在任何地方使用任何复制构造函数。所以一切都是肤浅的。但是 this.dept=dept 正在创建一个新的参考,这是我的问题。这是预期的行为吗?谢谢。