浅克隆与深克隆的区别
1、浅克隆:对当前对象进行克隆,并克隆该对象所包含的8种基本数据类型和String类型属性(拷贝一份该对象并重新分配内存,即产生了新的对象);但如果被克隆的对象中包含除8中数据类型和String类型外的其他类型的属性,浅克隆并不会克隆这些属性(即不会为这些属性分配内存,而是引用原来对象中的属性)。
2、深克隆:深克隆是在浅克隆的基础上,递归地克隆除8种基本数据类型和String类型外的属性(即为这些属性重新分配内存而非引用原来对象中的属性)
浅克隆与深克隆的特点
1、被克隆的对象的类应实现 Cloneable 接口,并重写 clone() 方法
2、浅克隆中由于除8中数据类型和String类型外的其他类型的属性不会被克隆,因此当通过新对象对这些属性进行修改时,原对象的属性也会同时改变。而深克隆则已经对这些属性重新分配内存,所以当通过新对象对这些属性进行修改时,原对象的属性不会改变。
代码示例
浅克隆:
public class Dog implements Cloneable{
private int id;
private Cat cat;
public Cat getcat() {
return cat;
}
public void setcat(Cat cat) {
this.cat = cat;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Dog(int id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class Cat {
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat(int id,String name) {
this.id = id;
this.name = name;
}
}
测试类:
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog(1);
Cat cat = new Cat(1,"jin");
dog.setcat(cat);
Dog dog2 = (Dog) dog.clone();
//修改dog2的id
dog2.setId(2);
//修改后与原来的id比较
System.out.println("dogId:"+dog.getId()+"--->dog2Id:"+dog2.getId());//dogId:1--->dog2Id:2
//修改cat的id
dog.getcat().setId(2);
System.out.println("cat1Id:"+dog.getcat().getId()+"--->cat2Id:"+dog2.getcat().getId());//cat1Id:2--->cat2Id:2
System.out.println("dog object same="+(dog==dog2));//false
System.out.println("dog object equals="+(dog.equals(dog)));//true
System.out.println("cat object same="+(dog.getcat()==dog2.getcat()));//true
System.out.println("cat object equals="+(dog.getcat().equals(dog.getcat())));//true
}
}
结果:
dogId:1--->dog2Id:2
cat1Id:2--->cat2Id:2
dog object same=false
dog object equals=true
cat object same=true
cat object equals=true
结论:
1、由System.out.println("dogId:"+dog.getId()+"--->dog2Id:"+dog2.getId());//dogId:1--->dog2Id:2 可以看出修改新克隆对象(dog2)的8种基本类型和String属性时,原属性不变,
2、由System.out.println("cat1Id:"+dog.getcat().getId()+"--->cat2Id:"+dog2.getcat().getId());//cat1Id:2--->cat2Id:2 可以看出修改被克隆对象(dog)所包含的对象属性(cat)时,新克隆对象(dog2)的属性(cat)也会改变。
3、由System.out.println("dog object same="+(dog==dog2));//false 可以看出克隆前后两个dog对象不是同一个对象
4、由System.out.println("cat object same="+(dog.getcat()==dog2.getcat()));//true 可以看出克隆前后cat对象为同一对象
深克隆:
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public class Dog implements Cloneable,Serializable{
private static final long serialVersionUID = 1L;
private int id;
private Cat cat;
public Cat getcat() {
return cat;
}
public void setcat(Cat cat) {
this.cat = cat;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public Dog(int id) {
this.id = id;
}
@Override
protected Object clone() throws CloneNotSupportedException {
try {
//序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
//写入到当前类(也可以写入到文件)
oos.writeObject(this);
//反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (Object) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
System.out.println("克隆出错"+e.getStackTrace());
return null;
}
}
}
import java.io.Serializable;
public class Cat implements Cloneable ,Serializable{
private static final long serialVersionUID = 1L;
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Cat(int id,String name) {
this.id = id;
this.name = name;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
测试类:与浅克隆的测试类一样
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
Dog dog = new Dog(1);
Cat cat = new Cat(1,"jin");
dog.setcat(cat);
Dog dog2 = (Dog) dog.clone();
dog2.setId(2);
System.out.println("dogId:"+dog.getId()+"--->dog2Id:"+dog2.getId());//dogId:1--->dog2Id:2
dog.getcat().setId(2);
System.out.println("cat1Id:"+dog.getcat().getId()+"--->cat2Id:"+dog2.getcat().getId());//cat1Id:2--->cat2Id:1
System.out.println("dog object same="+(dog==dog2));//false
System.out.println("dog object equals="+(dog.equals(dog)));//true
System.out.println("cat object same="+(dog.getcat()==dog2.getcat()));//false
System.out.println("cat object equals="+(dog.getcat().equals(dog.getcat())));//true
}
}
结果:
dogId:1--->dog2Id:2
cat1Id:2--->cat2Id:1
dog object same=false
dog object equals=true
cat object same=false
cat object equals=true
结论:
1、由System.out.println("dogId:"+dog.getId()+"--->dog2Id:"+dog2.getId());//dogId:1--->dog2Id:2 可以看出修改新克隆对象(dog2)的8种基本类型和String属性时,原属性不变,
2、由System.out.println("cat1Id:"+dog.getcat().getId()+"--->cat2Id:"+dog2.getcat().getId());//cat1Id:2--->cat2Id:1 可以看出修改被克隆对象(dog)所包含的对象属性(cat)时,新克隆对象(dog2)的属性(cat)不会改变,因为cat也被克隆了。
3、由System.out.println("dog object same="+(dog==dog2));//false 可以看出克隆前后两个dog对象不是同一个对象
4、由System.out.println("cat object same="+(dog.getcat()==dog2.getcat()));//false 可以看出克隆前后cat对象不是同一对象
注意:实现深克隆有以下两个条件
1、被克隆的类必须实现 Cloneable ,Serializable 接口;
2、重写 clone() 方法。即将被克隆类进行序列化与反序列化
重写 clone() 方法如下:
@Override
protected Object clone() throws CloneNotSupportedException {
// return super.clone();
try {
//序列化
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
//写入到当前类(也可以写入到文件)
oos.writeObject(this);
//反序列化
ByteArrayInputStream bais = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
return (Object) ois.readObject();
} catch (Exception e) {
e.printStackTrace();
System.out.println("克隆出错"+e.getStackTrace());
return null;
}
}
版权声明:本文为weixin_43520586原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。