由于我的项目面临技术困难,因此提出了这个问题。
问题: 我需要克隆一个类的Object,它从第三方库类扩展属性(继承)(我们无权修改其内容)
让我用下面的例子来解释:
家长班:
public class UnChangeableBaseClass {
//fields and Methods
}
儿童班:
class DerivedLocalClass extends UnChangeableBaseClass implements Cloneable {
// local fields and methods
public Object clone(){
Object clonedObj= null;
try{
clonedObj = super.clone();
}
catch(CloneNotSupportedException e){
//log exceptions
}
}
}
当我尝试执行此操作时,super.clone()
方法引用类 - UnChangeableBaseClass
类型,并且它不会覆盖Object clone()
方法。我相信所有类都使用java.lang.Object class
扩展,隐式protected Object clone()
方法将继承到此父类。所以,我认为Derived Class中的这个方法会覆盖Parent / Object克隆方法。但是在运行时JVM搜索UnChangeableBaseClass
中明确定义的克隆方法。希望我能以正确的方式解释而不会让你感到困惑。
我的问题如下:
如何在这种典型情况下实现克隆方法,我们无法添加任何方法
在父类中让super.clone()
调用对象克隆方法。
如果无法进行上述情况,是否有其他方法可以克隆派生类
对象(通过考虑上述场景中的所有限制)
最后,只是想知道这种JVM行为的原因(如上所述)。
答案 0 :(得分:2)
如何在这种典型情况下实现克隆方法,我们不能 在父类中添加任何方法以使super.clone()调用Object 克隆方法。
好吧,因为clone
方法是Object
类中的受保护方法,所以它也可以在超类UnChangeableBaseClass
中访问,因为它从Object
类扩展。因此,基本上您可以使用基类clone
中的super.clone()
访问DerivedLocalClass
方法。
如果上述情况不可能,还有其他方法可以克隆 派生类对象(通过考虑上面的所有限制 场景)
我建议,即使您可以选择使用clone
方法来克隆对象,也不应该使用它。最好在派生类中使用 copy-constructor
,并向基类构造函数添加super()
调用。
另请参阅Effective Java - Item#11 - Override clone judiciously
,其中表明clone
方法已被破坏。
在这篇文章中: - Josh Bloch on Design - Copy Constructor versus Cloning
,您希望看到Bloch
的第一段: -
如果您已经阅读了我的书中有关克隆的项目,特别是如果您 在线之间阅读,你会知道我认为克隆是深刻的 破碎。有一些设计缺陷,其中最大的就是 可克隆的接口没有克隆方法。这意味着它 根本不起作用:制作Cloneable不会说什么 关于你可以用它做什么。相反,它说的是什么 它可以在内部完成。它说如果通过调用super.clone 反复它最终调用Object的clone方法,这个方法会 返回原始的字段副本。
所以,结论是,你的copy constructor
中可以有DerivedLocalClass
,它会返回调用对象的副本,如下所示: -
public DerivedLocalClass(DerivedLocalClass obj) {
this.setVar(obj.getVar());
}
答案 1 :(得分:2)
JVM克隆通过使用Marker接口Cloneable而不是查找Object.clone()来工作。确实,所有Java类都将继承克隆方法,但根据克隆方面的javadoc
A class implements the Cloneable interface to indicate to the Object.clone() method that it is legal for that method to make a field-for-field copy of instances of that class.
在你的情况下你不能做super.clone()因为它没有标记为Cloneable。如果你不能改变父类,那么你必须自己制作一份副本。
答案 2 :(得分:1)
我正在使用java 1.7,我在运行OP给出的代码时没有遇到任何问题。 除非超类重写了克隆以抛出异常,否则我认为即使超类不声明自己是克隆的,这也应该有效。
我会注意到
public Object clone()
没有覆盖clone方法,它缺少throws子句。
答案 3 :(得分:0)
正确的方法签名在
之下@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
Clone是Protected
类中的Object
方法,因此您可以在类中访问它,如果您从中扩展它。
只需要从super.clone()
上调用方法clone()
的对象调用internalClone
方法this
,这是当前的类对象。
internalClone((Cloneable) this);
因此,clone()
内的Object
方法只会在CloneNotSupportedException
Cloneable
clone()
之前抛出protected
我看到一些关于克隆方法的误解
Object
方法在clone()
课程中为child.clone()
,因此您无法在课堂外调用public
。例如Cloneable
除非您覆盖它并进行访问Cloneable
CloneNotSupportedException
是标记界面,如果您没有标记类clone()
,那么如果您调用super.clone
方法super.clone
superclasses (except Object)
返回的对象中的任何字段都不需要修改。 x.clone().getClass() == x.getClass()
来获取返回的对象。如果一个类及其所有public class Child extends UnChangeableBaseClass
implements
Cloneable {
int index = 0;
public Child(int index) {
this.index = 10;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
遵守此约定,那么{{1}}就是这种情况。 以下代码工作正常
{{1}}
参考文献: