Object.clone()方法引申出的浅克隆、深克隆、java原型模式的实现、不可变类的实现

本文详细介绍了Java中的克隆技术,包括浅克隆和深克隆的概念,以及如何实现深克隆。通过实例展示了如何创建不可变类,并探讨了原型模式在Java中的应用。此外,还讨论了两种实现深克隆的方法:直接深度遍历和序列化实现,强调了在处理可变类成员时的注意事项。
摘要由CSDN通过智能技术生成

一  快速回忆

     二者需要实现cloneable接口,且重写clone方法,此方法一定要是public 否则你无法使用该克隆对象,并且第一句一定要是super.clone();

    浅克隆:

               只拷贝对象的基本属性。

               引用类型成员变量不拷贝,则克 隆出来的对象与原对象中对应的成员变量指向同样的地址,即克隆对象若改变对应的属性,则原对象对应的属性也会改变 ,这显然不是我们所希望的。

    深克隆:

                 拷贝对象的基本属性,包括其类型,拷贝对象的引用类型。

                  如果被克隆的对象有引用对象,那么经过深克隆后将产生两个对象,即俩个对象(引用成员变量)所指向的内容不一样。

     

   如果某一个类的成员变量不是原始变量(八大基本类型)或者不可变类(如String、包装类型),必须通过在成员初始化或者get方法时通过深度clone(生成一个不同于原对象成员变量的成员变量)来确保成员变量的不可变性。


   当克隆对象只有基本类型时,不含引用类型,可以用浅拷贝实现。

   当克隆对象含有引用类型时,必须用深克隆来实现。否则克隆出来的对象还有与原对象相同的引用变量,相互影响,不是我们所希望的。

          深克隆具体实现有: 

                   1  深度克隆

                   引用成员变量所对应的类(暂理解为父类)实现Cloneable接口,且重写clone方法中。包含引用变量所在的类(组合引用成员的类)实现Cloneable接口,重写clone方法,并在其clone方法,加上引用成员变量已重写的clone()方法。具体如下面二中的例子:

                                             p.birth = (Date) this.birth.clone();

                   2  使用Serializable接口,序列化实现深克隆。 

                       引用成员变量所对应的父类仅实现serializable接口。引用成员变量所在的类(组合引用成员的类)实现serializable、cloneable接口,并重写clone方法。在要实现克隆的方法中,使用ObjectInputStream 、ObjectOutPutStream克隆对象。

  

                 序列化方式实现深克隆效率不高,没有直接深度克隆的效率高。         

                                                                      

二 详细理解


       Object.clone()方法用于对象的拷贝,它会把在堆上的对象所占用的内存空间(地址)拷贝一份然后返回,这样就形成一个新的对象(个人理解)。因为每个对象所占的空间内都有一个指向其类数据的指针,也就是指向方法区中类数据(这个类数据可以通过Class对象进行访问,可以简单、直接的理解为就是指向代表其类的Class对象)。JVM会通过这个指针来判断一个对象的类型,由于把整个对象空间拷贝,所以拷贝的对象的类指针也指向相同的类对象,这就确保了obj.clone().getClass()==obj.getClass(),即它们具有相同的类型

        还有一点,因为只是简单的将对象的空间进行复制,所以如果类具有引用类型的实例变量的话,也只是将这个引用进行拷贝,并不复制其引用的对象。这就导致拷贝对象的引用实例变量与原对象的指向相同的对象,这就是传说中的“浅拷贝”。

      如果实例变量引用的对象是不可变的,类似于String,则拷贝对象与原对象不能互相影响,这样的拷贝是成功的。但是如果引用的是可变对象,它们就会影响彼此,对于成功的拷贝而言,这是不允许的可以对可变的实例变量对象进行特殊处理,以实现拷贝对象和原对象 不能相互影响的“深拷贝”

      由于Object.clone()方法是protected的,所以它只能在lang包中的类或是其子类的方法内部被调用,所以,如果像下面这样调用,会编译出错,在Person kobe_bak=kobe.clone();报错,说clone只能在Object的protected作用域访问。

[c-sharp]  view plain copy print ?
  1. class Person implements Cloneable  
  2. {  
  3.     private int age;  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值