1.概念定义:
官方概念:
翻译的有点懵 没事来看下面三张图:
如下图:
举个栗子:
Task类:
public class Task implements Cloneable { private Integer id; private String name; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
1.引用复制
private static void test3() { Task task1 = new Task(); Task task2 = task1; System.out.println(task1); System.out.println(task2); }
2.这个有点复杂了。是假象深copy为浅copy 因为以上的Task中只含有基本类型和一个final的String对象 所以结果为深拷贝 这里很多大佬都是用
task1.getName() == task2.getName()为true的话就是浅copy 在这有个疑问:因为String的特性是每当我们创建字符串常量时,JVM会首先检查字符串常量池,
如果该字符串已经存在常量池中,那么就直接返回常量池中的实例引用。
如果字符串不存在常量池中,就会实例化该字符串并且将其放到常量池中。
由于String字符串的不可变性我们可以十分肯定常量池中一定不存在两个相同的字符串
所以这个引用的地址没有改变,而且复制对象的各种行为也没有影响到被拷贝对象的行为。
下面会继续尝试(在末尾进行尝试揭秘)
private static void test4() throws CloneNotSupportedException {
Task task1 = new Task();
task1.setId(1);
task1.setName("aaa");
Task task2 = (Task) task1.clone();
System.out.println(task1);
System.out.println(task2);
System.out.println(task1.getName() == task2.getName()); //
task1.setName("bbb");
System.out.println(task2.getName());
}
结果:
Task@4554617c
Task@74a14482
3.
Task类:
public class Task implements Cloneable { private Integer id; private String name; private TaskDetail taskDetail; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public TaskDetail getTaskDetail() { return taskDetail; } public void setTaskDetail(TaskDetail taskDetail) { this.taskDetail = taskDetail; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
TaskDetail类:
import com.sun.org.apache.xpath.internal.operations.String; public class TaskDetail { private String tdname; private Integer tdid; public String getTdname() { return tdname; } public void setTdname(String tdname) { this.tdname = tdname; } public Integer getTdid() { return tdid; } public void setTdid(Integer tdid) { this.tdid = tdid; } }
private static void test5() throws CloneNotSupportedException{ Task task1 = new Task(); task1.setId(1); task1.setName("aaa"); TaskDetail td1 = new TaskDetail(); td1.setTdid(11); td1.setTdname("tdaaa"); task1.setTaskDetail(td1); Task task2 = (Task) task1.clone(); System.out.println(task1.getTaskDetail()); System.out.println(task2.getTaskDetail()); }
结果为:
TaskDetail@4554617c
TaskDetail@4554617c
所以默认的clone为浅copy(浅层次复制)
以上怎么变成深拷贝呢?
public class Task implements Cloneable { private Integer id; private String name; private TaskDetail taskDetail; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public TaskDetail getTaskDetail() { return taskDetail; } public void setTaskDetail(TaskDetail taskDetail) { this.taskDetail = taskDetail; } @Override protected Object clone() throws CloneNotSupportedException { Task task = (Task) super.clone(); task.taskDetail = (TaskDetail) taskDetail.clone(); return task; } }
public class TaskDetail implements Cloneable{ private String tdname; private Integer tdid; public String getTdname() { return tdname; } public void setTdname(String tdname) { this.tdname = tdname; } public Integer getTdid() { return tdid; } public void setTdid(Integer tdid) { this.tdid = tdid; } @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
private static void test5() throws CloneNotSupportedException{ Task task1 = new Task(); task1.setId(1); task1.setName("aaa"); TaskDetail td1 = new TaskDetail(); td1.setTdid(11); td1.setTdname("tdaaa"); task1.setTaskDetail(td1); Task task2 = (Task) task1.clone(); System.out.println(task1.getTaskDetail()); System.out.println(task2.getTaskDetail()); }
结果为:
TaskDetail@4554617c
TaskDetail@74a14482
继续final class的问题:
Task类:
public class Task implements Cloneable { private Integer id; private String name; private TaskDetail taskDetail; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public TaskDetail getTaskDetail() { return taskDetail; } public void setTaskDetail(TaskDetail taskDetail) { this.taskDetail = taskDetail; } @Override protected Object clone() throws CloneNotSupportedException { // Task task = (Task) super.clone(); // task.taskDetail = (TaskDetail) taskDetail.clone(); return super.clone(); } }
TaskDetail类:
public final class TaskDetail { private String tdname; private Integer tdid; public String getTdname() { return tdname; } public void setTdname(String tdname) { this.tdname = tdname; } public Integer getTdid() { return tdid; } public void setTdid(Integer tdid) { this.tdid = tdid; } }
测试:
private static void test5() throws CloneNotSupportedException{ Task task1 = new Task(); task1.setId(1); task1.setName("aaa"); TaskDetail td1 = new TaskDetail(); td1.setTdid(11); td1.setTdname("tdaaa"); task1.setTaskDetail(td1); Task task2 = (Task) task1.clone(); System.out.println(task1.getTaskDetail()); System.out.println(task2.getTaskDetail()); task2.getTaskDetail().setTdname("bbbb"); System.out.println(task1.getTaskDetail().getTdname());//task2的修改已经影响了task1的内容。 }
结果为:
TaskDetail@4554617c
TaskDetail@4554617c
bbbb
欢迎来喷。。。