Java深拷贝,浅拷贝

时间:2023-01-02 19:48:16

1.对象的clone:
要想实现某个类的对象的clone,可以按以下几点来操作:
1.这个类必须实现Cloneable这个标示性接口;
2.这个类要重写父类Object的clone方法;
3.把这个clone方法访问权限设置为public;
4.这个clone方法中调用了super.clone()方法,返回当前类的引用;
5.以上四步仅仅是实现了对象的浅复制,浅拷贝,浅克隆。
注意:对象的浅拷贝,得到一个新的对象,这个新的对象里面的原生数据类型都是拷贝出来的;但是拷贝出来的对象的引用类型指向的和原对象指向的对象是一样的,也就是说,对于引用类型变量,拷贝的只是引用变量,这个引用指向的对象并没有拷贝。

2.要实现对象的深拷贝:
1.思路,利用序列化和反序列化来获得一个对象的拷贝;
2.这个对象必须实现Serializable接口;
3.在这个对象的类中定义一个方法,方法里面通过将这个类的对象写到一个流中,再从流中读取回来这么一个操作,得到一个新的这个类的对象;
注意:深拷贝和浅拷贝相比,会把对象中的所有变量都拷贝出一份新的,因此相同引用类型的变量会分别指向两个不同的对象,但是这两个对象的内容是一样的。

实现深克隆工具类

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

//浅克隆 实现了基本数据类型的拷贝,但是对于引用类型(对象类型)的话,Obj1和克隆出来的Obj2引用数据类型指向的是同一个对象;
//深克隆就是把 对象中的引用数据类型重新拷贝一份;
//通过把对象先读取到内存中,再从内存中取出来,实现对象的深克隆;
//前提,对象实现了Serializable接口;
//工具类 实现类对象的深克隆
public class CloneUtil {
@SuppressWarnings("unchecked")
public static <T> T cloneTo(T src) throws RuntimeException {
ByteArrayOutputStream memoryBuffer = new ByteArrayOutputStream();
ObjectOutputStream out = null;
ObjectInputStream in = null;
T dist = null;
try {
out = new ObjectOutputStream(memoryBuffer);
out.writeObject(src);
out.flush();
in = new ObjectInputStream(new ByteArrayInputStream(memoryBuffer.toByteArray()));
dist = (T) in.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (out != null)
try {
out.close();
out = null;
} catch (IOException e) {
throw new RuntimeException(e);
}
if (in != null)
try {
in.close();
in = null;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return dist;
}
}

测试类

public class Administrator implements Cloneable {
private User user;
private Boolean editable;
public Administrator(User user, Boolean editable) {
this.user = user;
this.editable = editable;
}

@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public int hashCode() {

}
@Override
public boolean equals(Object obj) {

}
}

浅克隆

import java.util.Date;
import org.junit.Test;
public class Test {
@Test
public void testAdministratorClone() throws CloneNotSupportedException {
Administrator a1 = new Administrator(new User("Kent", "123456", new Date()), true);
Administrator a2 = a1;
Administrator a3 = (Administrator) a1.clone();

System.out.println(a1 == a2); // true
System.out.println(a1.equals(a2)); // true

System.out.println(a1 == a3); // false
System.out.println(a1.equals(a3)); // true

System.out.println(a1.getUser() == a3.getUser()); //true ! 浅克隆还是指向同一个对象
System.out.println(a1.getUser().equals(a3.getUser())); //true
}
}

深克隆

public class Test {

@Test
public void testCloneTo() {
Administrator src = new Administrator(new User("Kent", "123456", new Date()), true);
Administrator dist = BeanUtil.cloneTo(src);

System.out.println(src == dist); // false
System.out.println(src.equals(dist)); // true

System.out.println(src.getUser() == dist.getUser()); //false ! 深克隆 对象也克隆了一份
System.out.println(src.getUser().equals(dist.getUser())); //true
}

}