提问人:Gray 提问时间:3/2/2023 最后编辑:Gray 更新时间:3/2/2023 访问量:113
如何使用复制构造函数在不实现 cloneable() 或 arraycopy() 的情况下创建 Object 数组内容的深层副本?
How to use a copy constructor to create a deep-copy of an Object array's contents without implementing cloneable() or arraycopy()?
问:
我需要创建一个数组内容的副本,该数组内容由不同类型的各种对象组成。但是,我不能使用显式强制转换来检查对象的类型,也不能使用可克隆的接口/arraycopy 方法。
首先,我创建了一个所有其他类扩展的超类,但我不确定如何使用特定类的复制构造函数。我最初的尝试是:
public Building(Object obj) {
try {
this.windows= ((House)obj).windows;
this.basement = ((House)obj).basement;
} catch (ClassCastException ex) {
this.windows = 0;
this.basement = false;
}
... (various other try-catch blocks here)
}
驱动程序是:
public static Building[] copyBuildings(Building[] objects) {
Building[] objList = new Building[objects.length];
for (int i = 0; i < objects.length; i++) {
objList[i] = new Building(objects[i]);
}
return objList;
}
但是,这并没有像我想要的那样正确地调用子类的复制构造函数,因为它根本没有引用它们。我不知道如何继续。
请记住,缺少显式类型转换,如果我在运行时不知道对象的显式类型,是否可以调用 Object 的复制构造函数(我是否需要更改当前的代码)?还是多态性不以这种方式起作用?
任何帮助将不胜感激!(以及一般反馈,我不太习惯使用 stackoverflow)
答:
1赞
Stephen C
3/2/2023
#1
显然,您有一个包含各种子类型的子类型。并且您想要创建深层副本。Building[]
Building
不能通过实现复制构造函数来执行此操作。Building
为什么?
因为构造函数 for 只能构造一个实例。它无法构造实例...或或 a 或 ...Building
Building
House
Hotel
Church
但是,有多种替代方法可以奏效:
在 和 它的每个子类型中实现。
Cloneable
Building
实现一个工厂方法或类,以便从另一个工厂方法或类创建。让它使用(或 Java 18+ 模式开关)来区分子类,然后为每个子类型使用适当的构造函数;例如:
Building
instanceof
if (building instanceof House) { return new House((House) building); } else if (building instanceof Hotel) { return new Hotel((Hotel) building); } else ...
使用反射。这很复杂,但您不需要为层次结构中的每个类或子类编写代码。
每种替代方案都有优点和缺点,我们无法建议哪一种最适合每种用例。当然,它们都不是所有用例的完美选择。
评论
0赞
Gray
3/3/2023
非常详细的答案,我很感激。如果我考虑我不能在任何地方(无论是在驱动程序中还是在 Building 类中)进行类型转换的限制,请导入任何外部类,也不使用 Cloneable 接口。还有可能吗?
1赞
Stephen C
3/3/2023
不。不可能。即使是反射方法也需要类型转换,而开关模式是 + 类型转换的一种花哨形式。(虽然我想这取决于你所说的“类型转换”的确切含义;即你是否在谈论语法......或者语法导致发生什么。instanceof
0赞
Gray
3/3/2023
通过类型转换,我指的是语法本身。我在查找被复制对象的实际类型方面受到限制。虽然多亏了你,现在更清楚了,但我不确定有什么样的隐藏解决方案(如果有的话)。再次感谢!
评论