java对象的克隆
摘取至https://blog.****.net/ztchun/article/details/79110096
一.对象赋值
如果直接对象赋值,例如:stu2 = stu1
那么情况将是:栈中两个对象名称指向同一块堆内存。更改任何一个对象中的值都会导致另一个的值改变,因为就是同一块内存空间。
二.浅克隆
被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常), 该接口为标记接口(不含任何方法)
覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象。
即在覆写的clone()方法中直接调用super.clone()方法,再转型至对象的变量类型即可
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return stu;
}
此时的情况就是对象中的值类型成员变量被拷贝了一份,但是引用类型的变量只是把地址拷贝了一份,就是说引用类型的数据成员还是公用同一份内存地址的。
三.深克隆
在浅克隆的基础上将引用类型也拷贝一份,实现:
首先, 在引用类型的成员变量的本身的类定义中也覆写clone(),调用super.clone();
再在要拷贝的类覆写的clone()方法中调用引用类型变量的clone()方法。
例如:要拷贝Student类的对象,该类中有一个引用类型的变量:private Address addr;
则首先在Address类中覆写clone()方法:
class Address implements Cloneable {
private String add;
public String getAdd() {
return add;
}
public void setAdd(String add) {
this.add = add;
}
@Override
public Object clone() {
Address addr = null;
try{
addr = (Address)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
return addr;
}
}
再在Student类覆写的clone()方法中加入调用Address类的clone()方法:
@Override
public Object clone() {
Student stu = null;
try{
stu = (Student)super.clone(); //浅复制
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
stu.addr = (Address)addr.clone(); //深度复制
return stu;
}
四.其他深克隆的方法
1.工具类BeanUtils和PropertyUtils进行对象复制
2.、通过序列化实现对象的复制
序列化就是将对象写到流的过程,写到流中的对象是原有对象的一个拷贝,而原对象仍然存在于内存中。通过序列化实现的拷贝不仅可以复制对象本身,而且可以复制其引用的成员对象,因此通过序列化将对象写到一个流中,再从流里将其读出来,可以实现深克隆。需要注意的是能够实现序列化的对象其类必须实现Serializable接口,否则无法实现序列化操作。