[英]super.clone() operation not works in Derived Class
之所以提出這個問題,是因為我的項目面臨技術難題。
問題:我需要克隆一個類的對象,在該對象中它擴展了第三方庫類的屬性(繼承)(在該類中,我們無權修改其內容)
讓我用下面的例子解釋:
家長班:
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()
方法引用的是Class- UnChangeableBaseClass
Type,並且它不會覆蓋Object clone()
方法。 我相信所有類都使用java.lang.Object class
類進行了擴展, protected Object clone()
隱式protected Object clone()
方法將繼承到此Parent類。 因此,我以這種方式認為派生類中的此方法將覆蓋“父/對象”克隆方法。 但是在運行時JVM中,搜索在UnChangeableBaseClass
顯式定義的克隆方法。 希望我以正確的方式進行解釋,不要讓您感到困惑。
我的問題如下:
在這種無法添加任何方法的典型情況下,如何實現克隆方法
在父類中具有super.clone()
來調用對象克隆方法。
如果以上情況是不可能的,是否有其他方法可以克隆派生類
對象(考慮上述情況下的所有限制)
最后,僅要了解這種JVM行為的原因(如上所述)。
在這種典型情況下,我們如何實現克隆方法,在這種情況下,我們不能在父類中添加任何方法來讓super.clone()調用對象克隆方法。
好吧,由於clone
方法是Object
類中的一種受保護方法,因此,由於clone
方法是從Object
類擴展的,因此在超級類UnChangeableBaseClass
也可以訪問它。 因此,基本上,您可以使用super.clone()
從基類DerivedLocalClass
訪問clone
方法。
如果以上情況不可能,是否有其他方法克隆派生類對象(通過考慮上述情況中的所有限制)
我建議,即使您可以選擇使用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方法,則此方法將返回原始字段的副本。
因此,結論是,您可以在DerivedLocalClass
擁有一個copy constructor
,該copy constructor
將向您返回調用對象的副本,如下所示:-
public DerivedLocalClass(DerivedLocalClass obj) {
this.setVar(obj.getVar());
}
JVM克隆通過使用Marker接口Cloneable而不是尋找Object.clone()來工作。 的確,所有Java類都將繼承clone方法,但是根據javadoc的說法,它是Cloneable的
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(),因為它沒有被標記為可克隆。 如果您不能更改父類,則必須自己復制它。
我正在使用Java 1.7,在運行OP給定的代碼時沒有任何問題。 除非超類具有重寫的克隆以引發異常,否則我認為即使超類未聲明自身可克隆,此方法也應起作用。
我會注意到
public Object clone()
沒有覆蓋clone方法,它缺少throws子句。
正確的方法簽名如下
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
Clone是Object
類中的Protected
方法,因此您可以在類內部以及從其進行擴展時訪問。 super.clone()
僅需要從對象上調用clone()
方法,該對象在當前類對象上this
方法調用internalClone
。
internalClone((Cloneable) this);
因此,如果調用Object
實例不是Cloneable
,則Object
內部的上面clone()
方法只會拋出CloneNotSupportedException
我看到一些關於克隆方法的誤解
clone()
方法在Object
類內部protected
因此您不能在類外部調用clone()
。 例如child.clone()
除非您覆蓋它並public
訪問 Cloneable
是標記接口,如果不標記Cloneable
類,則調用clone()
方法將得到CloneNotSupportedException
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();
}
}
參考文獻:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.