如果不应该更新我的原始列表的副本

时间:2016-11-05 18:40:27

标签: java arraylist

我有一些代码:

private List<Attributes> SplitDataBasedOnNextBranchToTraverse(Branches nextNonLeafBranchToSearch, List<Attributes> attributes) {
    List<Attributes> newAttributeListToReturn = attributes;

        for (Attributes attribute: newAttributeListToReturn){
            for (Branches branches : attribute._branches){
                branches.CheckRowExists(nextNonLeafBranchToSearch.ReturnAllRows());
            }
        }

    return newAttributeListToReturn;
}

我有一个全局的对象列表,我将其传递给一个方法,我将该列表的副本。副本列表将被更改,现在应该与我传入的全局列表不同。但是,当我调试我的代码并检查全局列表时,它匹配我的方法中列表的更改为什么?我不希望全局列表改变它需要保持不变!任何帮助我如何通过使两个列表彼此独特来阻止这种情况发生将非常感激。

1 个答案:

答案 0 :(得分:1)

分配只会将l1(这是一个参考)复制到l2。它们都会引用同一个对象。

创建浅拷贝非常简单:

List<Attributes> newAttributeListToReturn = new ArrayList<Attributes>(attributes); 

(就像一个例子。)

===================================== TL; DR

Java通过引用操作对象,所有对象变量都是引用。但是,Java不通过引用传递方法参数;它按值传递它们。以badSwap()方法为例:

public void badSwap(int var1, int var2) { 
     int temp = var1; 
     var1 = var2; 
     var2 = temp; 
 }

badSwap()返回时,作为参数传递的变量仍将保持其原始值。如果我们将参数类型从int更改为Object,该方法也将失败,因为Java也会按值传递对象引用。现在,这里变得棘手:

public void tricky(Point arg1, Point arg2) { 
    arg1.x = 100; 
    arg1.y = 100; 
    Point temp = arg1; 
    arg1 = arg2; 
    arg2 = temp; } 
public static void main(String [] args) { 
    Point pnt1 = new Point(0,0); 
    Point pnt2 = new Point(0,0); 
    System.out.println("X: " + pnt1.x + " Y: " +pnt1.y); 
    System.out.println("X: " + pnt2.x + " Y: " +pnt2.y); 
    System.out.println(" "); tricky(pnt1,pnt2); 
    System.out.println("X: " + pnt1.x + " Y:" + pnt1.y); 
    System.out.println("X: " + pnt2.x + " Y: " +pnt2.y); }

如果我们执行此main()方法,我们会看到以下输出:

X: 0 Y: 0 
X: 0 Y: 0 
X: 100 Y: 100 
X: 0 Y: 0

该方法成功地改变了pnt1的值,即使它是按值传递的;但是,pnt1pnt2的交换失败了!这是混乱的主要原因。在main()方法中,pnt1pnt2只不过是对象引用。将pnt1pnt2传递给tricky()方法时,Java会像任何其他参数一样按值传递引用。这意味着传递给方法的引用实际上是原始引用的副本。下面的图1显示了Java将对象传递给方法后指向同一对象的两个引用。 Figure 1. After being passed to a method, an object will have at least two references

Java按值复制并传递引用,而不是对象。因此,方法操作将改变对象,因为引用指向原始对象。但由于引用是副本,因此交换将失败。如图2所示,该方法引用swap,但不引用原始引用。不幸的是,在方法调用之后,只剩下未经过修改的原始引用。要使交换在方法调用之外成功,我们需要交换原始引用,而不是副本。

Figure 2. Only the method references are swapped, not the original ones

大卫·弗拉纳根(请参阅参考资料)的O'Reilly的Java坚果壳说得最好:“Java通过引用操纵对象',但它通过值传递对方法的对象引用。'”结果,你不能写交换对象的标准交换方法。

Source