我正在为每个实体编写自定义克隆方法。对于深层复制,有一种方法可以检测循环引用,或者我必须手动找出它并将克隆限制为单向而不是双向。
例如我们使用hibernate,因此User对象具有对Address和Address的引用,具有对User的引用。试图查看是否可以执行地址和用户的深层复制而不会遇到循环引用问题
答案 0 :(得分:7)
要实现此功能,您需要一个已克隆对象的引用Map。我们实现了这样的深度克隆:
在我们的实体基类中:
public void deepClone() {
Map<EntityBase,EntityBase> alreadyCloned =
new IdentityHashMap<EntityBase,EntityBase>();
return deepClone(this,alreadyCloned);
}
private static EntityBase deepClone(EntityBase entity,
Map<EntityBase,EntityBase> alreadyCloned) {
EntityBase clone = alreadyCloned.get(entity);
if( clone != null ) {
return alreadyClonedEntity;
}
clone = newInstance(entity.getClass);
alreadyCloned.put(this,clone);
// fill clone's attributes from original entity. Call
// deepClone(entity,alreadyCloned)
// recursively for each entity valued object.
...
}
答案 1 :(得分:1)
@Daniel:非常感谢你的回答!
我只是根据我的需要使用你的代码并对其进行了一些修改,这使得它更容易与子类一起使用。也许其他人对此感兴趣,所以这是我的基类代码:
/**
* Perform a deep clone.
*
* @return Deep Clone.
* @throws CloneNotSupportedException
*/
@SuppressWarnings("unchecked")
public VersionedEntityImpl deepClone() throws CloneNotSupportedException {
Map<VersionedEntityImpl, VersionedEntityImpl> alreadyCloned = new IdentityHashMap<VersionedEntityImpl, VersionedEntityImpl>();
return deepClone(this, alreadyCloned);
}
/**
* Perform a deep clone.
*
* @param entity
* @param alreadyCloned
* @return Deep Clone.
* @throws CloneNotSupportedException
*/
@SuppressWarnings("unchecked")
protected VersionedEntityImpl deepClone(VersionedEntityImpl entity,
Map<VersionedEntityImpl, VersionedEntityImpl> alreadyCloned) throws CloneNotSupportedException {
if (entity != null) {
VersionedEntityImpl clone = alreadyCloned.get(entity);
if (clone != null) {
return clone;
}
clone = entity.clone();
alreadyCloned.put(entity, clone);
return entity.deepCloneEntity(clone, alreadyCloned);
}
return null;
}
/**
* Method performing a deep clone of an entity (circles are eliminated automatically). Calls
* deepClone(entity,alreadyCloned) recursively for each entity valued object.
*
* @param clone
* @param alreadyCloned
* @return clone
* @throws CloneNotSupportedException
*/
protected abstract VersionedEntityImpl deepCloneEntity(VersionedEntityImpl clone,
Map<VersionedEntityImpl, VersionedEntityImpl> alreadyCloned) throws CloneNotSupportedException;
要放入子类的内容:
@SuppressWarnings("unchecked")
@Override
protected VersionedEntityImpl deepCloneEntity(VersionedEntityImpl clone,
Map<VersionedEntityImpl, VersionedEntityImpl> alreadyCloned) throws CloneNotSupportedException {
// fill clone's attributes from original entity. Call
// deepClone(entity,alreadyCloned)
// recursively for each entity valued object.
if (this.associatedItems != null) {
List<SomeClass> listClone = new LinkedList<SomeClass>();
for (SomeClass someClass: this.associatedItems) {
listClone.add((SomeClass) super.deepClone(someClass, alreadyCloned));
}
((SomeOtherClass) clone).setAssociatedItems(listClone);
}
((SomeOtherClass) clone).setYetAnotherItem((YetAnotherClass) super.deepClone(this.yai, alreadyCloned));
return clone;
}
目前还不完美,但现在可以很好地完成工作:)