Java 调用super.clone()方法时向下广播
考虑以下程序Java 调用super.clone()方法时向下广播,java,downcast,cloneable,Java,Downcast,Cloneable,考虑以下程序 class A implements Cloneable { String str = null; public void set(String str) { this.str = str; } @Override public A clone() { A a = null; try { a = (A) super.clone();
class A implements Cloneable {
String str = null;
public void set(String str)
{
this.str = str;
}
@Override
public A clone()
{
A a = null;
try {
a = (A) super.clone();
if(a.str!=null) {
System.out.println(a.str);
}
else {
System.out.println("null");
}
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
return a;
}
public static void main (String args[])
{
A a = new A();
a.set("1234");
A b = a.clone();
}
}
为什么上述程序的输出为1234且不为空
我希望为空,因为我的理解如下
有人能告诉我们在向下广播时发生了什么吗?1234是正确的结果。。。让我们看看原因: 创建一个新的
a
实例:
A a = new A();
将值设置为A.str
a.set("1234");
克隆a
首先,请注意,我们使用的是来自实例a
的clone()
方法,所以我们来看看:
@Override
public A clone()
{
// create a NEW instance, it does not set a to null!!!
// to reference the caller (a.clone in main)
// you must use this keyword i.e: this.str = null
A a = null;
try {
// call Cloneable::clone() method
a = (A) super.clone();
// now a is filled with data of this instance so print 1234
if(a.str!=null) {
System.out.println(a.str);
}
// unused code in this case
else {
System.out.println("null");
}
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// return cloned instance
return a;
}
1234是正确的结果。。。让我们看看原因: 创建一个新的
a
实例:
A a = new A();
将值设置为A.str
a.set("1234");
克隆a
首先,请注意,我们使用的是来自实例a
的clone()
方法,所以我们来看看:
@Override
public A clone()
{
// create a NEW instance, it does not set a to null!!!
// to reference the caller (a.clone in main)
// you must use this keyword i.e: this.str = null
A a = null;
try {
// call Cloneable::clone() method
a = (A) super.clone();
// now a is filled with data of this instance so print 1234
if(a.str!=null) {
System.out.println(a.str);
}
// unused code in this case
else {
System.out.println("null");
}
}
catch (CloneNotSupportedException e) {
e.printStackTrace();
}
// return cloned instance
return a;
}
从文档中删除
创建并返回此对象的副本。“复制”的确切含义可能取决于对象的类别。一般目的是,对于任何对象x,表达式:
x、 克隆()!=x
将为真,并且表达式:
x、 克隆().getClass()==x.getClass()
是的,但这些不是绝对的要求。而通常情况下:
x、 克隆().equals(x)
是的,这不是绝对的要求
如您所见,典型的情况是X.equals(XClone)=true
。
您不会遇到这种情况,因为A
没有覆盖equals
方法
此外:
类对象的克隆方法执行特定的克隆操作
[……]
此方法创建此对象类的新实例,并使用此对象对应字段的内容初始化其所有字段,就像通过赋值一样;字段的内容本身不是克隆的。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作
正如本文档所述,本机实现只创建您试图克隆的对象的浅拷贝。由于该行为,正确的输出是1234
,而不是null
,因为类中的字段
刚刚分配给克隆实例。来自文档
创建并返回此对象的副本。“复制”的确切含义可能取决于对象的类别。一般目的是,对于任何对象x,表达式:
x、 克隆()!=x
将为真,并且表达式:
x、 克隆().getClass()==x.getClass()
是的,但这些不是绝对的要求。而通常情况下:
x、 克隆().equals(x)
是的,这不是绝对的要求
如您所见,典型的情况是X.equals(XClone)=true
。
您不会遇到这种情况,因为A
没有覆盖equals
方法
此外:
类对象的克隆方法执行特定的克隆操作
[……]
此方法创建此对象类的新实例,并使用此对象对应字段的内容初始化其所有字段,就像通过赋值一样;字段的内容本身不是克隆的。因此,此方法执行此对象的“浅拷贝”,而不是“深拷贝”操作
正如本文档所述,本机实现只创建您试图克隆的对象的浅拷贝。由于该行为,正确的输出是1234
,而不是null
,因为类中的字段仅分配给克隆实例
方法将创建父类型(object)的新对象
在这种情况下)
不,这就是你的错误所在Object.clone()
将创建一个与调用它的对象的运行时类相同的运行时类的新实例,它是a
,而不是Object
。它会将调用对象中A
的所有字段浅拷贝到新对象中
当我们在clone()方法中进行向下转换时,会定义属性
在子类中,将使用其默认值初始化,因为
这是一个新对象
这没有任何意义,因为强制转换引用永远不会影响指向的对象的状态。如果引用指向的对象还不是A
的实例,则强制转换将抛出ClassCastException
。如果强制转换成功,则意味着引用指向的对象已经是A
的实例,而您只是使用不同类型的引用指向同一对象。你将永远不会得到一个带有石膏的“新对象”
方法将创建父类型(object)的新对象
在这种情况下)
不,这就是你的错误所在Object.clone()
将创建一个与调用它的对象的运行时类相同的运行时类的新实例,它是a
,而不是Object
。它会将调用对象中A
的所有字段浅拷贝到新对象中
当我们在clone()方法中进行向下广播时,则