【问题标题】:Cloning object with parent and children of the same class克隆具有同一类的父级和子级的对象
【发布时间】:2012-06-06 11:58:24
【问题描述】:

我有一个对象 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();
    }
}

【问题讨论】:

    标签: java clone


    【解决方案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();
        }
    }
    

    【讨论】:

    • Yanflea,感谢您的回答,但我找到了一个更快的解决方案,即将父母设置为孩子(我用解决方案编辑了我的问题)
    • 确实,这样更好,更简单。
    猜你喜欢
    • 2017-02-09
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多