何时分配给另一个的集合在java中具有不同的引用

时间:2014-02-14 16:03:42

标签: java collections

我有一个详细信息类型的ArrayList集合1。我将它分配给另一个集合2来对它进行操作,这样它就不会影响集合1.但是我看到集合1受到影响,因为引用了对象。 但我希望有两个不同的内存参考集合 - plz帮助我。

详细信息类 -

public class Details implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    private boolean enabled;

    private int number;

    public Details() {

    }

    public Details(int number, boolean enabled) {
        this.enabled = enabled;
        this.number = number;
    }

    public int getNumber() {
        return number;
    }

    public void setNumber(int number) {
        this.number = number;
    }

    public boolean getEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

}

主要课程 -

public static void main(String[] args) {

    List<Details> detailsList = new ArrayList<Details>();
    detailsList.add(new Details(10, false));
    detailsList.add(new Details(20, false));

    List<Details> newDetailsList = new ArrayList<Details>(detailsList);
    for(Details d : newDetailsList) {
        d.setEnabled(true);
        d.setNumber(50);
    }

    for(Details d : detailsList) {
        System.out.println("---" + d.getEnabled());
        System.out.println("---" + d.getNumber());
    }

}

输出 -

---true
---50
---true
---50

我从newDetailsList创建一个新集合detailsList并修改它......我看到更改已应用于detailsList集合。我怎么能避免那个

3 个答案:

答案 0 :(得分:1)

集合保存引用,集合的副本包含相同的引用

集合仅保存对象的引用。集合的副本只是一个新的引用,它包含对相同对象的相同引用。

除非您对集合中的所有对象进行 deep clone ,否则这将永远不会有效。

克隆在Java

中被破坏

这对于要复制的对象只是implements Clonable并不简单,并且有很多注意事项和almost impossible to get correct, to the point of not even bothering except in very simple cases,特别是如果有对象没有来源。

因此,Details对象的所有实例变量也必须被深度复制,作为其所有实例成员,以及他们的,以及他们的,以及他们的。而且你必须避免循环引用。就像我说的那样,并不像听起来那么简单。

有时这是不可能的,尤其是mutable个对象。但是有一个解决方案。

惯用解决方案

使Details对象不可变,并从原始对象创建新实例,并在构造新实例时设置所需的新值。

public class Details 
{
    private final Boolean enabled;

    private final Integer number;

    public Details(@Nonnull final Integer number, @Nonnull Boolean enabled) 
    {
        this.enabled = enabled;
        this.number = number;
    }

    public int getNumber() { return number;}

    public boolean getEnabled() { return enabled; }
}

一个好的方便工厂方法是:

public static Details newDetailsFromOldDetails(@Nonnull final Details details, @Nullable Integer number, @Nullable Boolean enabled)
{
    final Integer n = number == null ? details.getNumber() : number;
    final Boolean e = flag == null ? details.getBoolean() : enabled;
    return new Details(n, e)
}

答案 1 :(得分:0)

您复制列表,但不复制列表中包含的。因此,如果您修改复制的集合中的项目,更改仍将显示在原始集合中的项目中。您可能需要deep copy,这需要创建一个机制,通过该机制可以复制Details个对象,然后将原始列表项的副本添加到新列表中。相反,使用ArrayList的拷贝构造函数只是复制引用(即浅拷贝)。

答案 2 :(得分:-1)

克隆每个详细信息对象类型,如下所示 -

List<Details> newDetailsList = new ArrayList<Details>();
    for(Details t : detailsList) {
        newDetailsList.add(t.clone());
    }


public Details clone() {
    return new Details(this.number, this.enabled);
}

但是对于我在我的应用程序中真正使用的对象来说,这是不可能的。