克隆具有相同类的父级和子级的对象

时间:2012-06-01 08:35:19

标签: java clone

我有一个对象CategoryBean,其中定义了其他对象CategoryBean(其子对象)和另一对象CategoryBean(其父对象)的列表。

克隆它的孩子不是问题,但是克隆它的父母是行不通的。事实上,当我拥有我的对象A及其父P时,当我通过P并获得其子项列表(我应该在A处罚款)时,A与P的子项具有相同的引用。对象相等(“归属于“说话”,但不一样。

这是我的班级及其属性:

public class CategoryBean implements Externalizable, Cloneable {
    public static final boolean ACTIVE = true;
    public static final boolean INACTIVE = false;

    public static final int VALIDATED = 1;
    public static final int NON_OBSERVED = 2;
    public static final int IN_PROGRESS = 3;
    public static final int PARTIEL = 4;

    private String perimetre;
    private CategoryBean parentCategory;
    private List<CategoryBean> categoryList = new LinkedList<CategoryBean>();
    protected String title;
    /**
     * Category validée ou non
     */
    protected int state = NON_OBSERVED;
    /**
     * Category active ou inactive
     */
    protected boolean activated = ACTIVE;

    /**
     * @return the parentCategory
     */
    public CategoryBean getParentCategory() {
        return parentCategory;
    }

    /**
     * @param parentCategory
     *            the parentCategory to set
     */
    public void setParentCategory(CategoryBean parentCategory) {
        this.parentCategory = parentCategory;
    }

    /**
     * @return the perimetre
     */
    public String getPerimetre() {
        return perimetre != null ? perimetre.trim() : null;
    }

    /**
     * @param perimetre
     *            the perimetre to set
     */
    public void setPerimetre(String perimetre) {
        this.perimetre = perimetre != null ? perimetre.trim() : null;
    }

    /**
     * @return the category
     */
    public List<CategoryBean> getCategoryList() {
        return categoryList;
    }

    /**
     * @param category
     *            the category to set
     */
    public void setCategoryList(List<CategoryBean> categoryList) {
        this.categoryList = categoryList;
    }

    /**
     * @return the title
     */
    public String getTitle() {
        return title != null ? title.trim() : null;
    }

    /**
     * @param title
     *            the title to set
     */
    public void setTitle(String title) {
        this.title = title != null ? title.trim() : null;
    }

    /**
     * @return the state
     */
    public int getState() {
        return state;
    }

    /**
     * @param state
     *            the state to set
     */
    public void setState(int state) {
        this.state = state;
    }

    /**
     * @return the activated
     */
    public boolean isActivated() {
        return activated;
    }

    /**
     * @param activated
     *            the activated to set
     */
    public void setActivated(boolean activated) {
        this.activated = activated;
    }

    @Override
    public int hashCode() {
        if (parentCategory != null && categoryList != null && title != null) {
            return parentCategory.hashCode() + categoryList.hashCode() + title.hashCode();
        } else if (categoryList != null && title != null) {
            return parentCategory.hashCode() + categoryList.hashCode() + title.hashCode();
        } else {
            return super.hashCode();
        }
    }

    @Override
    public boolean equals(Object o) {
        if (o != null && o instanceof CategoryBean) {
            CategoryBean o2 = (CategoryBean) o;
            if (getPerimetre() != null && getTitle() != null && getParentCategory() != null) {
                return getPerimetre().equals(o2.getPerimetre()) && getTitle().equals(o2.getTitle())
                        && getParentCategory().equals(o2.getParentCategory());
            } else if (getPerimetre() != null && getTitle() != null && getPerimetre().equals(getTitle())) {
                return getPerimetre().equals(o2.getPerimetre()) && getTitle().equals(o2.getTitle());
            }
        }
        return super.equals(o);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void readExternal(ObjectInput input) throws IOException, ClassNotFoundException {
        setPerimetre((String) input.readObject());
        setParentCategory((CategoryBean) input.readObject());
        setCategoryList((List<CategoryBean>) input.readObject());
        setTitle((String) input.readObject());
        setState((Integer) input.readObject());
        setActivated((Boolean) input.readObject());
    }

    @Override
    public void writeExternal(ObjectOutput output) throws IOException {
        output.writeObject(getPerimetre());
        output.writeObject(getParentCategory());
        output.writeObject(getCategoryList());
        output.writeObject(getTitle());
        output.writeObject(getState());
        output.writeObject(isActivated());
    }

    @Override
    public CategoryBean clone() throws CloneNotSupportedException {
        try {
            CategoryBean clone = (CategoryBean) super.clone();
            clone.setPerimetre(getPerimetre());
            clone.setParentCategory(getParentCategory());

            List<CategoryBean> categoryListClone = null;
            if (getCategoryList() != null) {
                categoryListClone = new LinkedList<CategoryBean>();
                for (int i = 0; i < getCategoryList().size(); i++) {
                    categoryListClone.add(getCategoryList().get(i).clone());
                }
            }
            clone.setCategoryList(categoryListClone);

            clone.setTitle(getTitle());
            clone.setState(getState());
            clone.setActivated(isActivated());
            return clone;
        } catch (CloneNotSupportedException e) {
            throw new InternalError();
        }
    }
}

你知道我在克隆方法中做错了吗?

谢谢你的帮助:)

(编辑)解决方案:

public CategoryBean clone() throws CloneNotSupportedException {
    try {
        CategoryBean clone = (CategoryBean) super.clone();
        clone.setPerimetre(getPerimetre());

        List<CategoryBean> categoryListClone = null;
        if (getCategoryList() != null) {
            categoryListClone = new LinkedList<CategoryBean>();
            for (int i = 0; i < getCategoryList().size(); i++) {
                CategoryBean childClone = getCategoryList().get(i).clone();
                childClone.setParentCategory(clone);
                categoryListClone.add(childClone);
            }
        }
        clone.setCategoryList(categoryListClone);

        clone.setTitle(getTitle());
        clone.setState(getState());
        clone.setActivated(isActivated());
        return clone;
    } catch (CloneNotSupportedException e) {
        throw new InternalError();
    }
}

1 个答案:

答案 0 :(得分:1)

我认为您需要缓存克隆操作期间已克隆的父bean,以便在子项中调用clone.setParentCategory时,这是在属性中注入的克隆父项...

不确定它是否清晰:)......所以...这样的事情(小心,没有经过测试!):

@Override
public CategoryBean clone() throws CloneNotSupportedException {
    return cloneRecursive(new HashMap<CategoryBean, CategoryBean>());    
}

private CategoryBean cloneRecursive(Map<CategoryBean, CategoryBean> categoryBeans) throws CloneNotSupportedException {
    try {
        CategoryBean clone = (CategoryBean) super.clone();
        categoryBeans.put(this, clone);
        clone.setPerimetre(getPerimetre());
        clone.setParentCategory(categoryBeans.get(getParentCategory()));

        List<CategoryBean> categoryListClone = null;
        if (getCategoryList() != null) {
            categoryListClone = new LinkedList<CategoryBean>();
            for (int i = 0; i < getCategoryList().size(); i++) {
                categoryListClone.add(getCategoryList().get(i).cloneRecursive(categoryBeans));
            }
        }
        clone.setCategoryList(categoryListClone);

        clone.setTitle(getTitle());
        clone.setState(getState());
        clone.setActivated(isActivated());
        return clone;
    } catch (CloneNotSupportedException e) {
        throw new InternalError();
    }
}