2014-07-24 65 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