2014-07-24 104 views
2

所以我在我的書中如下:鑄造的clone()

Calendar calendar = new GregorianCalendar(2013,2,1); 
Calendar calendar1 = (Calendar)calendar.clone(); 

爲什麼有需要的鑄造(Calendar)?是不是calendar.clone()返回一個GregorianCalendar副本calendar?如果我刪除了投射,這是一個編譯錯誤,但如果我寫System.out.println(calendar.clone().getClass());它打印GregorianCalendar。是否calendar1指向calendar.clone()之後的GregorianCalendar(不投射)?

+1

來自[Wiki](http://en.wikipedia.org/wiki/Clone_%28Java_method%29)clone()方法的設計的一個缺點是clone()的返回類型是Object,並且需要被明確地轉換回適當的類型。但是,重寫clone()以返回適當的類型是可取的,並且不需要在客戶端進行投射(自J2SE 5.0起使用協變返回類型)。 –

+0

有關編譯時和運行時類型的一般註釋:如果您說'MyClass x = something'或者public MyClass method(),變量或函數結果可以是MyClass或其任何子類,但是編譯器只允許知道它是'MyClass'。所以如果你說'SubClass y = x',編譯器會拒絕它,因爲它不知道'x'是否是'SubClass'。當你運行它時,'x'可能是一個'SubClass'並不重要。如果你說'SubClass y =(SubClass)x',它會編譯,程序會在運行時檢查'x'是一個'SubClass'。 – ajb

+0

@ajb是的,我明白,但它不是我的情況,因爲GregorianCalendar是日曆的子類,如果我做System.out.print(calendar.clone()。getClass())它說克隆是GregorianCalendar ,而日曆可以保存對GregorianCalendar的引用;如果我寫日曆calendar1 =(GregorianCalendar)calendar.clone();它仍然是一個有效的表達式,我不會收到錯誤。那麼爲什麼顯式投射? – Tudor

回答

3

clone()返回Object。這就是爲什麼你需要將它轉換爲Calendar(編譯器不知道實際返回的實例的類型爲Calendar)。

一般情況下,你不能分配返回X一個變量,它的一個子類的X方法的返回值。

/** 
* Creates and returns a copy of this object. 
* 
* @return a copy of this object. 
*/ 
public Object clone() {} 

至於爲什麼它返回Object的原因,Calendar有子類,覆蓋clone方法。因此他們必須都返回相同的類型。

+1

我認爲他們可以讓'clone'返回單個類型,因爲協方差。但直到後來,協變才被添加到Java中。 – ajb

+0

好吧,它不是返回一個GregorianCalendar?在System.out.print(calendar.clone()。getClass());它表示這是一個GregorianCalendar返回的不是對象 – Tudor

+0

@PTTudor一個方法聲明爲其返回類型與它在特定方法調用中返回的實際類型(僅在運行時已知)之間存在差異。編譯器只知道前者,不能根據後者做出決定。 – Eran