Java之深浅clone
2019-11-01 本文已影响0人
任嘉平生愿
浅克隆
浅度克隆对于要克隆的对象,对于其基本数据类型的属性,复制一份给新产生的对象,对于非基本数据类型的属性,仅仅复制一份引用给新产生的对象,即新产生的对象和原始对象中的非基本数据类型的属性都指向的是同一个对象。
深克隆
深克隆简单的说就是:除了克隆自身对象,还对其他非基本数据类型的引用的其他以外的所有对象,都克隆了一遍。
java代码实战:
package deepshallowclone;
import java.io.IOException;
class DeepAndShallow {
public static void main(String []args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
Son son = new Son();
son.setName("son1");
son.setAge(10);
Father father1 = new Father();
father1.setName("father1");
father1.setAge(40);
father1.setSon(son);
//这是一个个引用
//father2=father1;
//这是一个浅拷贝
//Father father2 = (Father)father1.clone();
//这是一个深拷贝
Father father2 = (Father)father1.deepClone();
father2.getSon().setName("son2");
System.out.println(father1.getSon().getName());
father2.setName("father2");
System.out.println(father1.getName());
}
}
package deepshallowclone;
import com.fasterxml.jackson.annotation.JsonInclude;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.*;
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Father implements Serializable, Cloneable {
private String name;
private Integer age;
private Son son;
protected Object clone() throws CloneNotSupportedException {
Father cloned = (Father) super.clone();
return cloned;
}
public Father deepClone() throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Father) ois.readObject();
}
}
package deepshallowclone;
import lombok.Data;
import java.io.Serializable;
@Data
public class Son implements Serializable {
private String name;
private Integer age;
}
依次将上面的注解打开得到下面的结果
这是一个引用
son2
father2
这是一个浅拷贝
son2
father1
这是一个深拷贝
son1
father1
分析
1.Father father2=father1
这只是一个常规的引用所以father2指向的是father1的内存区域
2.Father father2 = (Father)father1.clone()
father2复制了father1的对象但是son这个对象任然是father2中的son指针指向的是father1的son的内存区域
注意Father一定要实现Cloneable接口
3.Father father2 = (Father)father1.deepClone()
这个是通过先序列化father1然乎再反序列化生成的一个father2新对象。
注意Father和Son两个类一定要实现Serializable接口
注意:
(Apache BeanUtils、PropertyUtils,Spring BeanUtils,Cglib BeanCopier)都是相当于克隆中的浅克隆。
以下是简单的性能分析:
cglib BeanCopier 15ms
Spring BeanUtil 4031ms
apache BeanUtils 18514ms.