【问题标题】:Array deep copy and shallow copy数组深拷贝和浅拷贝
【发布时间】:2014-03-06 07:03:21
【问题描述】:

我正在学习深拷贝和浅拷贝。

如果我们有两个数组:

int[]arr1={1,2,3,4,5};
int[]arr2={1,2,3,4,5};

问题:两个数组都指向相同的引用[1][2][3][4][5]

如果我更改 arr1[2] 会发生什么?它会更改 arr2[2] 吗?

当我们将一个数组(随机数组,不一定是arr1arr2)从main 传递到一个方法时,编译器会为该方法制作一个 数组副本,对吧?

如果 Java 编译器被重新编写以生成数组数据的 副本并将其发送到方法。 主中的原始数组会发生什么?我认为原始数组可能会根据方法发生变化并传回主数组。我不确定。

【问题讨论】:

  • 你试的结果如何?
  • 不,它不会改变它。
  • 两个数组不指向同一个东西。您初始化它们的方式,您创建了两个独立的数组,它们恰好以相同的内容开始。基元是值。 int[] arr1={1,2,3,4,5}; int[] arr2=arr1; 可能会进行更有趣的实验。
  • 想想int i = 1,如果有人做i++,程序中使用的每一个1会变成2吗?
  • 提示:1) 使用类而不是原始类型进行测试。 2) 使用IntegerString 等不可变类和StringBuilder 等可变类进行测试。

标签: java arrays deep-copy shallow-copy


【解决方案1】:

问题:两个数组都指向相同的引用 [1][2][3][4][5]。

不完全是。您的数组具有相同的内容。话虽如此,根据您的初始化,他们使用的数据不是共享的。然而,像这样初始化它会:

int[]arr1={1,2,3,4,5};
int[] arr2 = arr1

如果我改变 arr1[2] 会发生什么?它会改变 arr2[2] 吗?

根据上述问题的答案,不会。但是,如果您要按照我指出的那样更改初始化机制,那就可以了。

当我们传递一个数组(随机数组,不一定是arr1或arr2) 从 main 到方法,编译器制作数组的浅拷贝 方法,对吧?

您的方法将收到一个查找数组的位置,不会进行复制。

如果 Java 编译器被重新编写以制作和发送 数组数据到方法。中的原始数组会发生什么 主要的?我认为原始数组可能会根据 方法并传回主程序。我不确定。

如果您要创建数组的深层副本并将其发送到您的方法,并且您的方法将在该副本上工作,那么原始数组应该保持不变。

【讨论】:

    【解决方案2】:

    使用值初始化数组将始终分配新内存。 对于“int[]arr1 ={1,2,3,4,5};” jvm 将计算初始化数组的长度并在内存中分配所需的空间量。在这种情况下,jvm 为 5 个整数分配了内存。 当您执行“int []arr2={1,2,3,4,5}”时,同样的事情再次发生(jvm 为另外 5 个整数分配内存)。 因此更改 arr1[2] 不会反映 arr[2]。

    arr1[2]=10;
     System.out.println(arr2[2]); // this will still print 3
    

    如果你想让 arr2 指向 arr1 的内容,你应该这样做:

    int []arr2=arr1;
    

    这将是一个浅拷贝。这使得数组引用对象包含与 arr1 相同的值。现在如果你这样做:

    arr1[2]=10;
    System.out.println(arr2[2]); //this will print 10.
    

    现在,如果你想对一个数组做一个深拷贝(而不是像你做的那样重复初始化),正确的命令是:

    int arr2[] = Arrays.copyOf(arr1, arr1.length);
    

    这将与第一种情况类似(您的代码 - 更改 arr1 不会影响 arr2)。

    【讨论】:

      【解决方案3】:

      因为你有原始类型,所以你创建了独立的数组。演示深拷贝和浅拷贝:

      MyObject a = new MyObject("a");
      MyObject[] first = new MyObject[] {a};
      MyObject[] second = new MyObject[] {a};
      a.setName("b");
      System.out.println(second[0].getName());
      second[0].setName("c");
      System.out.println(first[0].getName());
      

      【讨论】:

        猜你喜欢
        • 2012-04-12
        • 2015-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-04-13
        • 1970-01-01
        • 2011-09-05
        • 1970-01-01
        相关资源
        最近更新 更多