黑马程序员_10_java克隆机制

来源:互联网 发布:阿里云域名解析到端口 编辑:程序博客网 时间:2024/05/20 14:27
--------------------------------android培训java培训期待与您交流! -----------------------------------

java克隆机制

克隆(clone):创建并返回此对象的一个副本。“副本”的准确含义可能依赖于对象的类。

通俗易懂的说法:将一个已经存在的实例对象,复制成多个实例,而且每个实例对象直接并没有联系,不会改一处,多处改变。也相当于Copy一样。

而克隆机制也分为深克隆(Shallow clone)与浅克隆(Deep clone),下面通过几个实例来演示。

首先:要克隆的类必须实现Cloneable,这是个许可证,么实现该接口,并重写其方法的类不能实现克隆。

1、定义一个类允许克隆。

class Aa implements Cloneable//克隆的前提{  Int i=1;;  @override//必须实现的方法protected Object clone() throws CloneNotSupportedException {return super.clone();  }}public class Demo05 {Public static void main(String[] args) throws CloneNotSupportedException {Aa a=new Aa();Aa b=(Aa)a.clone();  Aa c=a;System.out.println(a.i);System.out.println(b.i);System.out.println(c.i);}}

运行结果:

1
1
1

这样的结果很可能产生两种误会,对有没有过基础的会觉得,把a赋给了b和c。

对了解java指针机制的就会说,b和a都指向了a。两者都只对了一半。

下面增加两行代码就明白了;

  Aa a=new Aa();Aa b=(Aa)a.clone();Aa c=a;b.i=10;c.i=5;System.out.println(a.i);System.out.println(b.i);System.out.println(c.i)

运行结果:

5
10
5

显而易见,c变量指向了a,而b变量却是将a变量完全复制过来。很多时候我们都想得到某个对象的副本,暂时修改其属性又不能令对象的属性改变,很矛盾,这是这里可以用到clone关键字,但是这种克隆只能算得上浅度克隆(Shallow Clone)。

什么是深克隆?什么事浅克隆?

演示:在Aa这类中多了一个其他类的对象。

class Aa implements Cloneable{int i=1;B field=new B();@Overrideprotected Object clone() throws CloneNotSupportedException {return super.clone();}}class B {int i=1;public int getI() {return i;}public void setI(int i) {this.i = i;}}

然后主程序依旧按照常规克隆;

  Aa a=new Aa();Aa b=(Aa)a.clone();b.field.setI(10);System.out.println(a.field.getI());System.out.println(b.field.geitI());

运行结果:

 10
10

结果出乎意料,咋么又变成指针机制了?

要知道这些,先要了解Object在调用clone方法的时候都做了些什么。

Object在对某个实施Clone时对其对象一无所知,仅仅只是简单的做了一个Copy的动作,这就是浅克隆。但是在Aa类中却有一个引用型变量,当克隆时候,就把该对象的地址给克隆了,并没有克隆出实力对象。也可以验证下。

  System.out.println(a);System.out.println(b);System.out.println(a.field);  System.out.println(b.field);运行结果:  Aa@7800e9  Aa@83dae1  B@971d55  B@971d55

结果说明,ab不是同一个对象,但是a对象的成员fieldb对象的成员field,却是同一个对象,如图:

从图上可以看出,基本类型被克隆了,但是引用类型变量,却只克隆了地址,这种克隆也称作浅克隆(Shallow Clone)

怎么才能做到深度度克隆呢?

其实很简单,只需要重新定义Clone方法,对B类做特殊处理(Deep Clone)深度克隆

class Aa implements Cloneable{int i=1;B field=new B();@Overrideprotected Object clone() throws CloneNotSupportedException {Aa temp=(Aa)super.clone();//先克隆主体temp.field=(B)field.clone();//再克隆引用return temp;}}class B implements Cloneable//这个类也要实现克隆标记{int i=1;public int getI() {return i;}public void setI(int i) {this.i = i;}  //还要重写克隆方法protected Object clone() throws CloneNotSupportedException {return super.clone();}}这时候在打印:public static void main(String[] args) throws CloneNotSupportedException {Aa a=new Aa();Aa b=(Aa)a.clone();b.field.setI(100);b.i=10;System.out.println(a.i);System.out.println(b.i);System.out.println(a.field.getI());System.out.println(b.field.getI());}

运行结果:

1
10
1
100

现在内存中就是这样的:


这样就可以达到预想的效果,两个实例直接没有关系了。

总结:

Clone机制:存在两种方式。

1Shallow Clone;这种clone只对基本数据类型有效,对对象内的引用变量无效。

2Deep Clone;对对象所有成员都有效,前提是这些成员都实现了Cloneable接口

3、使用Clone将会抛出异常。

4、两种方式按自己需求而用,

--------------------------------android培训java培训期待与您交流! -----------------------------------

0 0
原创粉丝点击