浅克隆与深克隆的区别及特点

浅克隆与深克隆的区别

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版权协议,转载请附上原文出处链接和本声明。