Java浅复制与深复制的区别

简单的来说就是,在有指针的情况下,浅拷贝只是增加了一个指针指向已经存在的内存,而深拷贝就是增加一个指针并且申请一个新的内存,使这个增加的指针指向这个新的内存,采用深拷贝的情况下,释放内存的时候就不会出现在浅拷贝时重复释放同一内存的错误!

class Student implements Cloneable{ 
    private int number; 
 
    public int getNumber() { 
        return number; 
    } 
 
    public void setNumber(int number) { 
        this.number = number; 
    } 
     
    @Override 
    public Object clone() { 
        Student stu = null; 
        try{ 
            stu = (Student)super.clone(); 
        }catch(CloneNotSupportedException e) { 
            e.printStackTrace(); 
        } 
        return stu; 
    } 
} 
public class Test { 
     
    public static void main(String args[]) { 
         
        Student stu1 = new Student(); 
        stu1.setNumber(12345); 
        Student stu2 = (Student)stu1.clone(); 
     // Student stu2 = stu1.clone();   
        System.out.println("学生1:" + stu1.getNumber()); 
        System.out.println("学生2:" + stu2.getNumber()); 
         
        stu2.setNumber(54321); ////深度复制
     
        System.out.println("学生1:" + stu1.getNumber()); 
        System.out.println("学生2:" + stu2.getNumber()); 
    } 
} 
//学生1:12345
//学生2:12345
//学生1:12345
//学生2:54321
------------------------ ------------------------------------------------

class Address  { 
    private String add; 
 
    public String getAdd() { 
        return add; 
    } 
 
    public void setAdd(String add) { 
        this.add = add; 
    } 
     
}//Address 
 
class Student implements Cloneable{ 
    private int number; 
 
    private Address addr; 
     
    public Address getAddr() { 
        return addr; 
    } 
 
    public void setAddr(Address addr) { 
        this.addr = addr; 
    } 
 
    public int getNumber() { 
        return number; 
    } 
 
    public void setNumber(int number) { 
        this.number = number; 
    } 
     
    @Override 
    public Object clone() { 
        Student stu = null; 
        try{ 
            stu = (Student)super.clone(); 
        }catch(CloneNotSupportedException e) { 
            e.printStackTrace(); 
        } 
        return stu; 
    } 
} 
public class Test { 
     
    public static void main(String args[]) { 
         
        Address addr = new Address(); 
        addr.setAdd("杭州市"); 
        Student stu1 = new Student(); 
        stu1.setNumber(123); 
        stu1.setAddr(addr); 
         
        Student stu2 = (Student)stu1.clone(); 
         
        System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 
        System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 
        
        
        addr.setAdd("西湖区"); ///Address没有实现深度复制
        stu2.setNumber(456);////Student实现深度复制
        
        System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 
        System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 
        
    } 
} 
//学生1:123,地址:杭州市
//学生2:123,地址:杭州市
//学生1:123,地址:西湖区
//学生2:456,地址:西湖区

------------------------------------------------------------------------------------------------

//
//public class Test {
//
//}
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; 
    } 
} 
 
class Student implements Cloneable{ 
    private int number; 
 
    private Address addr; 
     
    public Address getAddr() { 
        return addr; 
    } 
 
    public void setAddr(Address addr) { 
        this.addr = addr; 
    } 
 
    public int getNumber() { 
        return number; 
    } 
 
    public void setNumber(int number) { 
        this.number = number; 
    } 
     
    @Override 
    public Object clone() { 
        Student stu = null; 
        try{ 
            stu = (Student)super.clone();   //浅复制  
        }catch(CloneNotSupportedException e) { 
            e.printStackTrace(); 
        } 
        stu.addr = (Address)addr.clone();   //深度复制  
        return stu; 
    } 
} 
public class Test { 
     
    public static void main(String args[]) { 
         
        Address addr = new Address(); 
        addr.setAdd("杭州市"); 
        Student stu1 = new Student(); 
        stu1.setNumber(123); 
        stu1.setAddr(addr); 
         
        Student stu2 = (Student)stu1.clone(); 
         
        System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 
        System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 
         
         addr.setAdd("西湖区"); ////把引用和引用指向的对象都复制了,只改变了stu1没有改变stu2
         stu2.setNumber(456);
        System.out.println("学生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd()); 
        System.out.println("学生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd()); 
    } 
} 

//学生1:123,地址:杭州市
//学生2:123,地址:杭州市
//学生1:123,地址:西湖区
//学生2:456,地址:杭州市

那么,怎样才能达到复制一个对象呢?

是否记得万类之王Object。它有11个方法,有两个protected的方法,其中一个为clone方法。

该方法的签名是:

protected native Object clone() throws CloneNotSupportedException;

因为每个类直接或间接的父类都是Object,因此它们都含有clone()方法,但是因为该方法是protected,所以都不能在类外进行访问。

要想对一个对象进行复制,就需要对clone方法覆盖。

一般步骤是(浅复制):

1. 被复制的类需要实现Clonenable接口(不实现的话在调用clone方法会抛出CloneNotSupportedException异常) 该接口为标记接口(不含任何方法)

2. 覆盖clone()方法,访问修饰符设为public。方法中调用super.clone()方法得到需要的复制对象,(native为本地方法)

总结:浅拷贝是指在拷贝对象时,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用进行拷贝,没有对引用指向的对象进行拷贝。

而深拷贝是指在拷贝对象时,对引用进行拷贝,同时会对引用指向的对象进行拷贝。

区别就在于是否对  对象中的引用变量所指向的对象进行拷贝。



你可能感兴趣的:(java,深复制,浅复制,克)