Java-克隆
Tags
#Java
1.假克隆
1.1测试代码
/**
* 假克隆
* <p>
* 只复制了对象,没有复制对象的引用
*/
private static void testFakeClone() {
//源对象
Bean bean = new Bean("张三", new Boss("老大"));
//这是克隆对象
Bean clone = bean;
clone.setName("小明");
clone.getBoss().setName("头");
System.out.println("这是原始数据:");
System.out.println(JSON.toJSONString(bean));
System.out.println("这是假克隆:");
System.out.println(JSON.toJSONString(clone));
}
1.2.输出结果:
//这是原始数据:
{
"boss": {
"name": "头"
},
"name": "小明"
}
//这是假克隆:
{
"boss": {
"name": "头"
},
"name": "小明"
}
1.3.结果分析
这里,我们修改了克隆对象的属性之后,源对象的属性也同样变了,关系如图所示(图是盗来的,不要纠结于名称):
./_image/2020-08-03-15-25-35.jpg
2.浅克隆
2.1.测试代码
/**
* 浅克隆
* <p>
* 既复制了对象,也复制了对象的引用
* 但是如果引用还存在引用,而更深层的引用如果没有实现cloneable接口,就还是会指向源对象
*/
private static void testShallowClone() {
//源对象
Bean bean = new Bean("张三", new Boss("老大"));
//这是克隆对象
Bean clone = bean.clone();
clone.setName("小明");
clone.getBoss().setName("头");
System.out.println("这是原始数据:");
System.out.println(JSON.toJSONString(bean));
System.out.println("这是浅克隆:");
System.out.println(JSON.toJSONString(clone));
}
需要Bean实现Cloneable接口:
/**
* 被克隆对象
* <p>
*/
public static class Bean implements Cloneable {
private String name;
private Boss boss;
public Bean() {
}
public Bean(String name, Boss boss) {
this.name = name;
this.boss = boss;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boss getBoss() {
return boss;
}
public void setBoss(Boss boss) {
this.boss = boss;
}
@Override
protected Bean clone() {
Bean clone = null;
try {
clone = (Bean) super.clone();
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
return clone;
}
}
2.2.输出结果
//这是原始数据:
{
"boss": {
"name": "头"
},
"name": "张三"
}
//这是浅克隆:
{
"boss": {
"name": "头"
},
"name": "小明"
}
2.3.结果分析
这里,我们修改了克隆对象的属性之后,源对象的name属性没有变,但是更深的引用boss却变了,说明此时源对象和克隆对象所引用的boss对象,其实还是同一个,关系如图所示(图是盗来的,不要纠结于名称):
./_image/2020-08-03-15-26-21.jpg
3.深克隆
3.1.测试代码
/**
* 深克隆
* <p>
* 将对象序列化,再反序列化生成一个新对象即可
* Serializable、Parcelable、JSON等均可
*/
private static void testDeepClone() {
//源对象
Bean bean = new Bean("张三", new Boss("老大"));
//这是克隆对象
String json = JSON.toJSONString(bean);
Bean clone = JSON.parseObject(json, Bean.class);
clone.setName("小明");
clone.getBoss().setName("头");
System.out.println("这是原始数据:");
System.out.println(JSON.toJSONString(bean));
System.out.println("这是深克隆:");
System.out.println(JSON.toJSONString(clone));
}
3.2.输出结果
//这是原始数据:
{
"boss": {
"name": "老大"
},
"name": "张三"
}
//这是深克隆:
{
"boss": {
"name": "头"
},
"name": "小明"
}
3.3.结果分析
./_image/2020-08-03-15-27-40.jpg
4.总结
- clone在平时项目中虽然用的不多,但是,区分深克隆和浅克隆却可以帮助我们理解java的内存结构
- clone的深克隆其实就是序列化和反序列化,这里有很多种选择,Serializable、Parcelable、JSON等均可
- clone方法不同于new方法,不会执行构造方法