在java中强制转换clone()

在java中强制转换clone(),java,calendar,clone,Java,Calendar,Clone,因此,我的书中有以下内容: Calendar calendar = new GregorianCalendar(2013,2,1); Calendar calendar1 = (Calendar)calendar.clone(); 为什么需要铸造(日历)?calendar.clone()不是正在返回calendar的副本吗?如果我删除强制转换,这是一个编译错误,但是如果我写入System.out.println(calendar.clone().getClass())它打印GregoriaCa

因此,我的书中有以下内容:

Calendar calendar = new GregorianCalendar(2013,2,1);
Calendar calendar1 = (Calendar)calendar.clone();
为什么需要铸造
(日历)
calendar.clone()
不是正在返回
calendar
的副本吗?如果我删除强制转换,这是一个编译错误,但是如果我写入
System.out.println(calendar.clone().getClass())它打印
GregoriaCalendar
calendar1
是否在
calendar.clone()
(未强制转换)之后指向一个
gregoriacalendar
。这就是为什么需要将其强制转换为
Calendar
(编译器不知道实际返回的实例的类型是
Calendar

通常,不能将返回
X
的方法的返回值分配给
X
的子类变量

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

至于它返回
对象
的原因,
日历
具有重写
克隆
方法的子类。因此,它们都必须返回相同的类型。

我认为,由于协方差的原因,它们可以使
clone
返回单个类型。但是协方差直到后来才被添加到Java中。它不是返回了一个GregoriaCalendar吗?in-System.out.print(calendar.clone().getClass());上面说这是一个Gregorianalendar而不是一个Object@PopTudor方法声明为其返回类型的类型与它在特定方法调用中返回的对象的实际类型(只有在运行时才知道)之间存在差异。编译器只知道前者,不能根据后者做出决定。clone()方法设计的一个缺点是clone()的返回类型是Object,需要显式转换回适当的类型。但是,重写clone()以返回适当的类型更可取,并且无需在客户端强制转换(使用协变返回类型,自J2SE 5.0以来)。关于编译时与运行时类型的一般评论:如果您说
MyClass x=something
public MyClass method()
,变量或函数结果可以是
MyClass
或其任何子类,但编译器只允许知道它是
MyClass
。因此,如果你说
子类y=x
,编译器会拒绝它,因为它不知道
x
是否是
子类。运行时,
x
可能是
子类
并不重要。如果您说
SubClass y=(SubClass)x
,它将编译,程序将在运行时检查
x
是否是
子类
@ajb是的,我理解,但这不是我的情况,因为GregorianCalendar是Calendar的子类,如果我执行System.out.print(Calendar.clone().getClass())它说克隆是一个格里高利安日历,日历可以包含对格里高利安日历的引用;如果我写calendar1=(GregorianCalendar)Calendar.clone();它仍然是一个有效的表达式,我没有得到任何错误。那么为什么要显式强制转换呢?@PopTudor您在
getClass()
中看到的是运行时类型。运行时类型对编译器并不重要,因为它无法预测运行时类型。据它所知,
clone()
的结果是一个
对象。当您运行它时,它是
gregoriacalendar
,这一事实对编译器来说根本不重要。您可以将
calendar1=
指定为
GregorianCalendar
,因为所有
GregorianCalendar
s都是
Calendar
s。但并非所有的
对象
s都是
日历
s。