目的
本文主要由实例的结果去分析深浅拷贝的不同,然后去理解深浅拷贝。对比深浅拷贝的结果,通过查看属性listString 和listUser 的值确定拷贝是否成功。
浅拷贝类
public class UserShallowClone implements Cloneable{
String name;
int age;
public List<String> listString = new ArrayList();
public List<UserShallowClone> listUser = new ArrayList();
public UserShallowClone(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected UserShallowClone clone(){
try {
return (UserShallowClone)super.clone();
}catch (Exception e){
return null;
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
简要分析:
实现了Cloneable接口,重写clone方法,次方法是native本地方法看不到源码。
核心方法只有super.clone();
深拷贝类
public class UserDeepClone implements Cloneable{
String name;
int age;
public List<String> listString = new ArrayList();
public List<UserDeepClone> listUser = new ArrayList();
public UserDeepClone(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected UserDeepClone clone(){
UserDeepClone d = null;
try {
d = (UserDeepClone) super.clone();
d.listUser = new ArrayList<>();
for(UserDeepClone u:listUser){
d.listUser.add(u.clone());
}
}catch (Exception e){
}
return d;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
简要分析:
此深拷贝类与浅拷贝类不同是对属性listUser 又做了一次克隆。作为对比listString 没有做克隆
测试类
public class CloneMain {
public static void main(String[] args) {
System.out.println("浅克隆-----------------------------------");
System.out.println("克隆前初始化");
UserShallowClone u = new UserShallowClone("原始人", 21);
u.listString.add("aaa");
u.listUser.add(new UserShallowClone("listUser1", 21));
System.out.println(u.listString);
System.out.println(u.listUser.size());
for (UserShallowClone d : u.listUser) {
System.out.println(d.getName() + d.getAge());
}
System.out.println("克隆后-----------------------------------");
UserShallowClone usc = u.clone();
usc.listString.add("bbb");
usc.listUser.add(new UserShallowClone("listUser2", 21));
usc.listUser.add(new UserShallowClone("listUser3", 21));
System.out.println(usc.listString);
System.out.println(usc.listUser.size());
for (UserShallowClone d : usc.listUser) {
System.out.println(d.getName() + d.getAge());
}
System.out.println("验证-----------------------------------");
System.out.println(u.listString);
System.out.println(u.listUser.size());
for (UserShallowClone d : u.listUser) {
System.out.println(d.getName() + d.getAge());
}
System.out.println("深克隆-----------------------------------");
UserDeepClone ud = new UserDeepClone("原始人", 21);
System.out.println("克隆前初始化");
ud.listString.add("aaa");
ud.listUser.add(new UserDeepClone("listUser1", 21));
System.out.println(ud.listString);
System.out.println(ud.listUser.size());
for (UserDeepClone d : ud.listUser) {
System.out.println(d.getName() + d.getAge());
}
System.out.println("克隆后");
UserDeepClone udc = ud.clone();
udc.listString.add("bbb");
udc.listUser.add(new UserDeepClone("listUser2", 21));
udc.listUser.add(new UserDeepClone("listUser3", 21));
System.out.println(udc.listString);
System.out.println(udc.listUser.size());
for (UserDeepClone d : udc.listUser) {
System.out.println(d.getName() + d.getAge());
}
System.out.println("验证-----------------------------------");
System.out.println(ud.listString);
System.out.println(ud.listUser.size());
for (UserDeepClone d : ud.listUser) {
System.out.println(d.getName() + d.getAge());
}
}
}
测试结果
浅克隆-----------------------------------
克隆前初始化
[aaa]
1
listUser121
克隆后-----------------------------------
[aaa, bbb]
3
listUser121
listUser221
listUser321
验证-----------------------------------
[aaa, bbb]
3
listUser121
listUser221
listUser321
深克隆-----------------------------------
克隆前初始化
[aaa]
1
listUser121
克隆后
[aaa, bbb]
3
listUser121
listUser221
listUser321
验证-----------------------------------
[aaa, bbb]
1
listUser121
重点来了,结果分析
1.深拷贝和浅拷贝之前都先对对象初始化,初始化值是一样的。
listString的值是aaa
listUser的用户名是listUser1,年龄是21
2.然后进行深浅拷贝的方法clone调用实现克隆
3.改变克隆后的listString和listUser的值,listString添加一个值bbb。listUser添加两个值
4.最后验证原来的值受影响了没
浅拷贝结果,分析原对象内的值改变了没
发现拷贝之前的listString的值多了个bbb,变成[aaa, bbb]
拷贝之前的listUser的值也变了,多了两个,结果如下:
3
listUser121
listUser221
listUser321
深拷贝结果,分析原对象内的值改变了没
listString值也变了[aaa, bbb],这是正常的,因为没做克隆。所以拷贝后实际引用的是同一个对象。克隆后的变了,原来的就也变了。
但是克隆后的listUser的值和克隆前的确不一样,说明成功拷贝,且不影响原来的,达到效果。