zoukankan      html  css  js  c++  java
  • Java的clone机制(及String的特殊性)

    1. Clone&Copy


    假设现在有一个Employee对象,Employee tobby =new Employee(“CMTobby”,5000),通
    常我们会有这样的赋值Employee cindyelf=tobby,这个时候只是简单了copy了一下reference,cindyelf和tobby都指向内存中同一个object,这样cindyelf或者tobby的一个操作都可能影响到对方。打个比方,如果我们通过cindyelf.raiseSalary()方法改变了salary域的值,那么tobby通过getSalary()方法得到的就是修改之后的salary域的值,显然这不是我们愿意看到的。我们希望得到tobby的一个精确拷贝,同时两者互不影响,这时候我们就可以使用Clone来满足我们的需求。Employee cindy=tobby.clone(),这时会生成一个新的Employee对象,并且和tobby具有相同的属性值和方法。

    2. Shallow Clone&Deep Clone


    Clone是如何完成的呢?Object在对某个对象实施Clone时对其是一无所知的,它仅仅是简单地执行域对域的copy,这就是Shallow Clone。这样,问题就来了咯,以Employee为例,它里面有一个域hireDay不是基本型别的变量,而是一个reference变量,经过Clone之后就会产生一个新的Date型别的reference,它和原始对象中对应的域指向同一个Date对象,这样克隆类就和原始类共享了一部分信息,而这样显然是不利的,过程下图所示:


    这个时候我们就需要进行deep Clone了,对那些非基本型别的域进行特殊的处理,例如本例中的hireDay。我们可以重新定义Clone方法,对hireDay做特殊处理,如下代码所示:

    class Employee implements Cloneable 
    
    { 
    public Object clone() throws CloneNotSupportedException 
    { 
    Employee cloned = (Employee) super.clone(); 
    cloned.hireDay = (Date) hireDay.clone() 
    return cloned; 
    } 
    }   


    3. Clone()方法的保护机制

    在Object中Clone()是被申明为protected的,这样做是有一定的道理的,以Employee

    类为例,通过申明为protected,就可以保证只有Employee类里面才能“克隆”Employee对象,原理可以参考我前面关于public、protected、private的学习笔记。

    4. Clone()方法的使用

    Clone()方法的使用比较简单,注意如下几点即可:

    a. 什么时候使用shallow Clone,什么时候使用deep Clone,这个主要看具体对象的域是什么性质的,基本型别还是reference variable

    b. 调用Clone()方法的对象所属的类(Class)必须implements Clonable接口,否则在调用Clone方法的时候会抛出CloneNotSupportedException。

    5. String

    String的特殊性在于: 

       因为他为引用型,而且他指向的值为常量,克隆出来的对象改变他的值。实际上是改变了克隆出来对象String类型成员的指向,不会影响被克隆对象的值及其指向。

    1、基本数据类型能自动实现深度clone

    2、String是一个例外。
       但对于我们编程来说可以和操作基本数据类型一样做,基本没影响。大大方便了我们的编程。

       String类型的变量clone后的表现好象也实现了深度clone,但其实只是一个假象。
       因为执行 cloned.name = "new";语句时,它作用相当于生成了一个新的string类型,然后又赋回给cloned.name。
       这是因为string被sun公司的工程师写成了一个不可更改的类(immutable class),在所有string类中的函数都不能更改自身的值。

    ==> 这告诉我们支持更方便实现克隆的一种途径:将自己定义的类编写为不可更改。

    3、StringBuffer需要做特殊处理
       String和StringBuffer有区别。
       可以借鉴类似技巧对StringBuffer型的变量实现克隆效果:sb=new StringBuffer(sb.toString());

  • 相关阅读:
    linux系统调用是通过软中断实现的吗
    Linux系统调用怎么和内核或底层驱动交互的
    strace命令
    linux 用户态和内核态以及进程上下文、中断上下文 内核空间用户空间理解
    C语言string.h常用函数总结
    shall的过去式和should怎么区分
    P(Y|X) 和 P(X,Y)
    Sourceinsight最佳配色方案及颜色字体调整方法
    float 为什么可以表示很大的整数
    协方差矩阵
  • 原文地址:https://www.cnblogs.com/mywy/p/5083095.html
Copyright © 2011-2022 走看看