JAVA对象的浅克隆和深克隆
浅克隆
- 对于基本数据类型的属性,复制一份给新的对象。
- 对于非基本数据类型的属性(对象),复制一份对象的引用给新的对象。
(即,新对象和旧对象中的非基本数据类型的属性的“指针”都
指向同一个对象)
浅克隆步骤
- 实现java.lang.Cloneable接口
- 重写java.lang.Object.clone方法
代码
class Test{
}
class Father implements Cloneable {
int i=5;
Test test = new Test();
public void setI(int i) {
this.i = i;
}
@Override
protected Object clone() {
try{
return super.clone();
}catch (CloneNotSupportedException e){
return null;
}
}
public static void main(String[] args) {
Father father = new Father();
//修改基本数据类型
father.setI(10);
//执行clone方法
Father clone =(Father) father.clone();
System.out.println(clone.i);
System.out.println(clone.test ==father.test);
System.out.println(father==clone);
}
}
运行结果
10
true
false
Process finished with exit code 0
深克隆
与浅克隆的区别是,对于非基本数据类型的属性,复制的不是原来的引用。
(即,新对象和旧对象中的非基本数据类型的属性的“指针” 不是
指向同一个对象)
深克隆步骤
- 实现java.io.Serializable
- 实现clone方法,将对象序列化转换为字节流,再将字节流反序列化为对象返回即可
代码
class Test implements Serializable{
}
class Father implements Serializable {
int i=5;
Test test = new Test();
public void setI(int i) {
this.i = i;
}
public Father clone(){
try {
// 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
ObjectOutputStream objout = new ObjectOutputStream(byteOut);
objout.writeObject(this);
//将流序列化成对象
ByteArrayInputStream bytein = new ByteArrayInputStream(byteOut.toByteArray());
ObjectInputStream objin = new ObjectInputStream(bytein);
return (Father) objin.readObject();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
Father father = new Father();
//修改基本数据类型
father.setI(10);
//执行clone方法
Father clone =(Father) father.clone();
System.out.println(clone.i);
System.out.println(clone.test ==father.test);
System.out.println(father==clone);
}
}
运行结果
10
false
false
Process finished with exit code 0
Tip:
实际场景中,很少使用克隆,更多的是对象属性之间的克隆。
一般使用BeanUtils
工具类的public static void copyProperties(Object source, Object target)
方法。