JAVA 深复制与浅复制

来源:互联网 发布:linux yum安装maven 编辑:程序博客网 时间:2024/06/03 17:10


一、引言
   对象拷贝(Object Copy)就是将一个对象的属性拷贝到另一个有着相同类类型的对象中去。在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用对象的部分或全部 数据。Java中有三种类型的对象拷贝:浅拷贝(Shallow Copy)、深拷贝(Deep Copy)、延迟拷贝(Lazy Copy)。

二、浅拷贝

1、什么是浅拷贝
   浅拷贝是按位拷贝对象,它会创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值;如果属性是内存地址(引用类型),拷贝的就是内存地址 ,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。


  在图中,SourceObject有一个int类型的属性 "field1"和一个引用类型属性"refObj"(引用ContainedObject类型的对象)。当对SourceObject做浅拷贝时,创建了CopiedObject,它有一个包含"field1"拷贝值的属性"field2"以及仍指向refObj本身的引用。由于"field1"是基本类型,所以只是将它的值拷贝给"field2",但是由于"refObj"是一个引用类型, 所以CopiedObject指向"refObj"相同的地址。因此对SourceObject中的"refObj"所做的任何改变都会影响到CopiedObject。

2、用例:

public class Subject {    private String name;    public Subject(String s) {       name = s;    }    public String getName() {       return name;    }    public void setName(String s) {       name = s;    } }public class Student implements Cloneable {     // 对象引用    private Subject subj;    private String name;    public Student(String s, String sub) {       name = s;       subj = new Subject(sub);    }    public Subject getSubj() {       return subj;    }    public String getName() {       return name;    }    public void setName(String s) {       name = s;    }    /**     *  重写clone()方法     * @return     */    public Object clone() {       //浅拷贝       try {          // 直接调用父类的clone()方法         return super.clone();       } catch (CloneNotSupportedException e) {          return null;       }    } }public class CopyTest {    public static void main(String[] args) {        // 原始对象        Student stud = new Student("John", "Algebra");        System.out.println("Original Object: " + stud.getName() + " - " + stud.getSubj().getName());        // 拷贝对象        Student clonedStud = (Student) stud.clone();        System.out.println("Cloned Object: " + clonedStud.getName() + " - " + clonedStud.getSubj().getName());        // 原始对象和拷贝对象是否一样:        System.out.println("Is Original Object the same with Cloned Object: " + (stud == clonedStud));        // 原始对象和拷贝对象的name属性是否一样        System.out.println("Is Original Object's field name the same with Cloned Object: " +     (stud.getName() == clonedStud.getName()));        // 原始对象和拷贝对象的subj属性是否一样        System.out.println("Is Original Object's field subj the same with Cloned Object: " +    (stud.getSubj() == clonedStud.getSubj()));        stud.setName("Dan");        stud.getSubj().setName("Physics");        System.out.println("Original Object after it is updated: " + stud.getName() + " - " +     stud.getSubj().getName());        System.out.println("Cloned Object after updating original object: " + clonedStud.getName() +     " - " + clonedStud.getSubj().getName());    }}
结果:

 Original Object: John - Algebra Cloned Object: John - Algebra Is Original Object the same with Cloned Object: false Is Original Object's field name the same with Cloned Object: true Is Original Object's field subj the same with Cloned Object: true Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Physics

三、深拷贝
1、什么是深拷贝
   深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。



在上图中,SourceObject有一个int类型的属性 "field1"和一个引用类型属性"refObj1"(引用ContainedObject类型的对象)。当对SourceObject做深拷贝时,创建了CopiedObject,它有一个包含"field1"拷贝值的属性"field2"以及包含"refObj1"拷贝值的引用类型属性"refObj2" 。因此对SourceObject中的"refObj"所做的任何改变都不会影响到CopiedObject

2、用例:(在浅复制的基础上修改)

public class Student implements Cloneable {    // 对象引用    private Subject subj;    private String name;    public Student(String s, String sub) {       name = s;       subj = new Subject(sub);    }    public Subject getSubj() {       return subj;    }    public String getName() {       return name;    }    public void setName(String s) {       name = s;    }    /**     * 重写clone()方法     *     * @return     */    public Object clone() {       // 深拷贝,创建拷贝类的一个新对象,这样就和原始对象相互独立      Student s = new Student(name, subj.getName());       return s;    } }

结果:

 Original Object: John - Algebra Cloned Object: John - Algebra Is Original Object the same with Cloned Object: false Is Original Object's field name the same with Cloned Object: true Is Original Object's field subj the same with Cloned Object: false Original Object after it is updated: Dan - Physics Cloned Object after updating original object: John - Algebra


四、延迟拷贝
   延迟拷贝是浅拷贝和深拷贝的一个组合,实际上很少会使用。 当最开始拷贝一个对象时,会使用速度较快的浅拷贝,还会使用一个计数器来记录有多少对象共享这个数据。当程序想要修改原始的对象时,它会决定数据是否被共享(通过检查计数器)并根据需要进行深拷贝。 
   延迟拷贝从外面看起来就是深拷贝,但是只要有可能它就会利用浅拷贝的速度。当原始对象中的引用不经常改变的时候可以使用延迟拷贝。由于存在计数器,效率下降很高,但只是常量级的开销。而且, 在某些情况下, 循环引用会导致一些问题。
0 0
原创粉丝点击