当前位置:编程学习 > JAVA >>

关于java对象克隆的问题

一个关于对象克隆的例子:

class Employee implements cloneable

{

public Employee(String n,Date s)

{

name = n;

salary = s;

}

public Employee clone() throws CloneNotSupportException

{

Employee x = (Employee) super.clone();

x.salary = (Date) salary.clone();

return x;

}

}

问题1:既然clone方法是object的一个protected方法,根据子类可以调用超类的protected方法的原则,为何不直接调用,而必须调用cloneable接口,定义其方法的方式进行操作,资料上的解释我确实看不明白。

问题2:public Employee clone() throws CloneNotSupportException,这个clone方法的申明中,为何要将其返回类型定义为Employee类型的?clone方法不是object类吗?

问题3:public Employee clone() throws CloneNotSupportException,还是这句话,为何要提前抛出异常,书中解释说,只要在clone方法中含有没有实现的类的对象,就要抛出异常,但是在程序中,Employee类和Date类已经都实现了啊。百思不解啊!

问题4:Employee x = (Employee) super.clone();这个程序段是java中的强制类型转换吗?我也大概明白super.clone()是调用object类的clone方法,但是在Employee类型中打上括弧有何意义?强制类型转换吗?

问题5:x.salary = (Date) salary.clone();同上!还是一样的问题没理解到其深刻含义。希望各位JAVA江湖的各位高手,各位满意答案,谢谢啦!

追问:关于问题1:已解决,补充一下,你解释的此时此刻的对象属性以及实例域的拷贝应该打着重符号,因为我终于理解到Date为可变子对象,在第一个时刻,你浅拷贝,但是Date对象是及时变化,下一个时刻,你就没有真正拷贝类对象的数据域。谢谢你,我终于理解到这点了,为何要应用cloneable接口。

关于问题2:public Employee clone() throws CloneNotSupportException这个是在类实现的接口中,定义子类自己的clone方法,其返回类型为Employee。其实书中不是这样的,而是public Object clone() throws CloneNotSupportException仍然采用超类进行定义。我误打误撞居然改正确了,在这里我再次希望你确认一下。

关于问题3:在类Employee实现接口的方法clone中,有了此类的构造器申明,为

public Employee(String n,Date s),那么问题来了,你说从上面程序段看不出Date类是否实现了cloneable接口,意思是如果实现了,就不会抛出异常,你能否举例,Date类如何实现cloneable接口?

关于问题4:谢谢,我已经理解到你说的了,但是问题又出来了,再看这个句子:Employee x = (Employee) super.clone();我百思不得其解的是super.clone()应该子类调用超类的clone方法吧,然后这个clone方法克隆的是超类的数据域吧,然后呢?再传参给类Employee的引用x。(这里的传参是地址的传递),那么这样一思考下来,我就又糊涂啦,再看这个句子:Employee x = (Employee) super.clone();申明类型为Employee的对象参数x,然后x他作为引用指向超类Object的数据域的拷贝,并进行强制类型转化,这样不对吧?请你再解释一下,谢谢了。

关于问题5:x.salary为何不能写成this.salary。

答案:问题1:

声明实现cloneable接口是为了让Employee类的对象能够通过调用自身的clone()方法实现实现“深层复制”操作,所谓“深层复制”指的就是对象字段的内容能够自我克隆,即此时此刻对象的安全拷贝,这与创建此对象的类的另一个新实例所使用的通常的内存分配方式不同,因为后者只是用被复制对象字段的内容初始化新对象的所有字段,实现cloneable接口就能保证对象使用前者的内存分配方式,尽管它只是一个标志(只有字段,没有方法),但是它有底层的一些功能。如果不实现cloneable,那么在Employee类的对象上调用clone()方法就会抛出CloneNotSupportedException异常。

问题2:

object类中有原始的clone()方法,但是Employee类继承自object类(object类是所有类的超类),所以override其clone()方法时可以将object类型改变为子类Employee的类型.

问题3:

因为从上面的代码不能看出Date类是否实现了cloneable接口,如果没有实现就必须抛出CloneNotSupportedException,否则在对象salary上调用clone方法将会导致在运行时出现问题。

问题4:

子类对象转化为父类时是隐式转换,父类对象转化为子类时是显式转换,必须使用()进行强制类型转换。

问题5:

从这里看来,salary对象引用指向的是Date类,如果Date类中没有重写clone()方法,那么salary.clone()返回的是Date类的超类对象的拷贝,这时就得使用强制类型转换。

问题1 调用接口是为了降低耦合,所谓耦合,简单的说,就是两个东西的关联关系。接口就是类似日常生活中的‘代理人’,某个类拥有某个功能,你要调用,直接找‘代理人’就行了,而不必关心这个功能到底这么实现的。而且,未来,你的类可能变了,比如改成person,而person里也有clone方法需要调用,此时,如果你代码是调用父类的clone,你就得重写代码,而如果是调用接口,只要person也实现cloneable接口就可以不重写代码。

问题2.因为return x的x是Employee类,所以返回类型定义为Employee。clone是object的,这里覆盖了object的clone()

问题3 这里的Date的clone方易做图抛出那个异常,所以你调用date的clone也必须抛出异常。而date类的clone方法里面是怎么写的,我们不知道。可能有像你书上写的含有没有实现的类的对象

问题4 是强制类型转换,括号,就是强制转成Employee类。因为等号左边是Employee类,等号两边的类型必须一致,所以要转换。当然,当等号左边是等号右边的父类时,可以自动类型转换,就不用强转啦。

问题5.x.salary是Date类型,而salary.clone()返回类型是object的,和左边的类型不一致,所以要强转

你问的问题,没太明白,可能有点难度。

上一个:有关于JAVA方面的资料吗?
下一个:java 52张 扑克牌 问题

CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,