JAVA基础篇-浅度和深度克隆的区别
2019-06-12 本文已影响83人
艺术类架构师
为什么需要克隆机制?
克隆是将对象的值拿过来,方便快速copy一个对象,java中有两种克隆方式,一个是浅度克隆,另外一个则是深度克隆(deep copy),有对比就有区别。
他们之间有什么区别?
浅度克隆是克隆对象的副本,克隆对象的引用,在JAVA中的实现方式是只需要实现标记接口Cloneable即可(标记该对象可以调用Object.clone()方法)
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.
浅度克隆代码示例:
import java.io.*;
import java.util.Objects;
import java.util.Objects;
/**
* Created by Administrator on 2019/6/12.
*/
public class ShallowCloneObject implements Cloneable {
private String name;
private int age;
private Object object;
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;
}
public Object getObject() {
return object;
}
public void setObject(Object object) {
this.object = object;
}
public static void main(String[] args) throws CloneNotSupportedException {
//源对象
ShallowCloneObject source=new ShallowCloneObject();
source.setAge(18);
source.setName("浅度克隆");
source.setObject(new Object());
System.out.println(source.equals(source.clone()));
//克隆出来的新对象
ShallowCloneObject target= (ShallowCloneObject) source.clone();
//克隆的对象属性是相等的,打印出true
assert target.getName()==source.getName();
System.out.println(target.getName()==source.getName());
assert target.getObject()==source.getObject();
System.out.println(target.getObject()==source.getObject());
}
}
深度克隆是指克隆对象的值,相当于值传递,实现方式是对象字节流进行序列化与反序列化转换式传输,深度克隆出来的对象里面包含的属性指向的是新的堆空间(注意的是如果用到对象字节流的话所有的对象属性包括自己都必须要实现序列化,基本类型除外)
深度克隆代码示例
import java.io.*;
import java.lang.reflect.Field;
import java.util.Objects;
/**
* Created by Administrator on 2019/6/12.
*深度克隆对象示例
*/
public class DeepCloneObject implements Serializable{
private String name;
private int age;
private SeriaObject object;
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;
}
public Object getObject() {
return object;
}
public void setObject(SeriaObject object) {
this.object = object;
}
public DeepCloneObject deepClone() throws IOException, ClassNotFoundException {
Field[] fields= this.getClass().getDeclaredFields();
java.security.AccessController.doPrivileged(
new java.security.PrivilegedAction<Void>() {
public Void run() {
for(Field fs:fields) {
fs.setAccessible(true);
}
return null;
}
});
//检测所有的属性是否是实现了序列化接口
for(Field f:fields){
if(f.getClass().isPrimitive()){
continue;
}
if(f.getClass().isInstance(Serializable.class)){
throw new RuntimeException("the field:["+f.getName()+"] must be implements Serializable interface exlude primitive class");
}
}
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
//将当前这个对象写到一个输出流当中,,因为这个对象的类实现了Serializable这个接口,所以在这个类中
//有一个引用,这个引用如果实现了序列化,那么这个也会写到这个输出流当中
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (DeepCloneObject) ois.readObject();
}
@Override
public String toString() {
return "DeepCloneObject{" +
"name=" + name +
", age=" + age +
'}';
}
static class SeriaObject extends Object implements Serializable{}
public static void main(String[] args) throws CloneNotSupportedException, IOException, ClassNotFoundException {
//源对象
DeepCloneObject source=new DeepCloneObject();
source.setAge(18);
source.setName("深度克隆");
source.setObject(new SeriaObject());
//克隆出来的新对象
DeepCloneObject target=source.deepClone();
//克隆的对象属性是相等的,打印出false
System.out.println(target.getName()==source.getName());
System.out.println(target.getObject()==source.getObject());
}
}
·