初始Java深克隆和浅克隆

1.浅复制与深复制概念
⑴浅复制(浅克隆)
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。换言之,浅复制仅仅复制所考虑的对象,而不复制它所引用的对象。

⑵深复制(深克隆)
被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量。那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。换言之,深复制把要复制的对象所引用的对象都复制了一遍。

2.接下来我将用代码的方式展示深克隆与浅克隆的区别

(1)浅复制(克隆)

          先创建一个Person类并且实现Serializableji接口(实现Serializableji接口的目的主要是为了深复制做准备),并且添加私有属性name以及构造方法和getName()方法,setName()方法。

                             

          再写个testShallowClone()方法,在这里我们实例化了三个Person类,通过Collections.addAll()方法将三个对象存储到集合lists当中去,通过调用clone()方法将lists集合复制到cloneLists当中,运行程序。

       

得到的结果是:

       

         第一个结果是false,说明coneLists和lists的地址不一样;第二个结果是true,说明lists下第一个对象p1的地址与clonelLists下第一个对象p1的地址是一样的,也就是说cloneLists在复制过程中并没有复制lists下的引用对象(p1,p2,p3),而是直接引用lists下的对象p1的地址。所以这就导致了要是改变cloneLists下对象的属性(也就是p1,p2,p3的name),那么lists下对应对象的属性也会改变。

      ⑵深复制(深克隆)

      通过对象的序列化和反序列化实现对象的复制,会将对象以及内部的数据全部复制一份.也就是说只有通过序列化和反序列化才能实现深克隆。首先写个实现对象序列化和反序列化的方法。

        这里我们用到了ByteArrayOutputStream,使用该类的对象作为临时存储输出流的对象.通过其提供的toByteArray获得数据存储到字节数组buff中,实现对象的序列化。并用ByteArrayInputStream作为输入流获取字节流,通过ObjectInputStream类下的readObject()方法实现对象的反序列化。

        测试环节:

      运行结果:

    

     第一个结果不必多说,第二个结果是false,发现cloneLists与lists下的对象指向不同的地址(虽然对象的name属性值是一样的),说明在深克隆过程中会将所复制对象的引用对象也给复制一遍,这就导致引用对象的地址不同,所以当你改变cloneLists的引用对象p1的name属性,lists的引用对象p1的name属性也就不会发生改变了,这便是深克隆。

 

      经过我的讲解希望大家对深克隆和浅克隆有初步的理解!!!