您有以下三种选择之一:
- 有一个方法
IAnimal
来深度克隆对象(由诸如 DOM 接口之类的库使用Node.cloneNode(boolean)
)
- 在所有实现中创建一个复制构造函数,该构造函数
IAnimal
采用具体类型并在接口契约中提出要求,然后使用反射来访问它
- 创建一个复制工厂,手动复制每个实现
- 使用 3rd-party 库,它通过自己的合约为您实现深度克隆,例如无参数构造函数、非最终字段、
Serializable
类等,就像这里列出的一样
复制方法
对于#1,请执行以下操作:
public interface IAnimal {
IAnimal cloneDeep();
}
在您的具体类型中实现它,然后调用该方法来复制它:
this.pet = pet.cloneDeep();
然后在界面中记录需求,大致如下:
此接口的实现必须返回一个不==
属于此实例的对象,并且必须进行深度克隆,以便对该对象的操作不会导致对返回的对象的操作,反之亦然。
为了与接口兼容,实现必须遵循这个契约,但这不会在编译时强制执行。
复制构造函数
尝试反射性地访问复制构造函数,然后声明接口中的所有具体实现都需要复制构造函数,这成为接口契约的一部分。然后每个实现将如下所示:
public class Dog implements IAnimal {
private String name;
public Dog(Dog dog) {
this.name = dog.name;
}
}
然后你只需要一个方法来复制每个实现:
public static <A extends IAnimal> A copy(A animal) {
Class<?> animalType = animal.getClass();
// This next line throws a number of checked exceptions you need to catch
return (A) animalType.getConstructor(animalType).newInstance(animal);
}
如果你有这个,在你的界面文档中添加一个声明来实现这个效果:
此接口的实现必须定义一个复制构造函数,该构造函数接受与其类相同类型或超类型的参数。此构造函数必须制作参数的深层副本,以便对该对象的操作不会导致对返回的对象的操作,反之亦然。
同样,这是运行时强制执行的。当构造函数不存在时,上面的copy
方法会抛出错误。NoSuchMethodException
复制工厂
这需要IAnimal
并使用instanceof
来决定将其传递给哪个方法,例如:
public static IAnimal copyAnimal(IAnimal animal) {
if (animal instanceof Dog)
return copyDog((Dog) animal);
if (animal instanceof Cat)
return copyCat((Cat) animal);
//...
else
throw new IllegalArgumentException("Could not copy animal of type: "
+ animal.getClass().getName());
}
copy
然后手动对每种类型的方法进行深度复制。