【问题标题】:Taking a copy of my original List gets updated when it shouldn't复制我的原始列表会在不应该更新时更新
【发布时间】:2016-11-05 18:40:27
【问题描述】:

我有一点代码:

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

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

【问题讨论】:

  • 您没有传递列表的副本,而是传递了一个参考并正在处理它
  • 你还没有创建一个新对象.. newAttributeListToReturn 是一个指向同一个全局 List 对象的新引用......
  • 您认为您在该代码中的哪个位置复制了列表本身,您为什么这么认为?

标签: java arraylist


【解决方案1】:

assignment 只会将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 将对象传递给方法后指向同一个对象的两个引用。

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

David Flanagan 撰写的 O'Reilly 的 Java in a Nutshell(请参阅参考资料)说得最好:“Java '通过引用'来操作对象,但它通过 '按值'将对象引用传递给方法。”因此,您无法编写交换对象的标准交换方法。

Source

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 2020-10-18
    • 2016-03-05
    • 1970-01-01
    • 1970-01-01
    • 2014-07-30
    • 2017-12-22
    相关资源
    最近更新 更多