Java detects circular references during user cloning

I write my own cloning method for each object. for a deep copy, is there a way to detect circular references, or do I need to manually figure this out and restrict cloning to be unidirectional rather than bidirectional.

For example, we use hibernate and, therefore, the User object has a link to Address and Address, has a link to the user. An attempt to find out whether it is possible to make a deep copy of the address, as well as the user, without resorting to round reference questions.

+5
source share
2 answers

To implement this, you need a map of links to already cloned objects. We implemented a deep clone like this:

:

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 attributes from original entity. Call
    // deepClone(entity,alreadyCloned) 
    // recursively for each entity valued object.
    ...
}
+7

@: !

, . , - , :

/**
 * 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 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;
}

, :)

+1

All Articles