代码之家  ›  专栏  ›  技术社区  ›  Cash-

将数组内容分配给另一个

  •  0
  • Cash-  · 技术社区  · 7 年前

    所以我对Java很陌生。

    我在做练习时遇到了这个问题。

    enter image description here

    我的解决方案

    public static void fillWithRandomNumbers (double[] values) {
    
        double[] numbers = new double[values.length];
    
        for(int i = 0 ; i < numbers.length ; i++){
    
        numbers[i] = Math.random();
        values[i] = numbers[i];                  // <---- That's the only thing I changed from the above code.
    
        }
    
    }
    

    从我的讲稿上可以看出。

    在Java中,赋值运算符可以用来复制基元数据类型变量,但不复制数组。

    enter image description here

    但当我试图运行上面问题中编写的代码并打印结果时。它给了我完整的随机数输出。

    产量

    --------------------Configuration: Test - JDK version 1.8.0_171 <Default> - <Default>--------------------
    0.5879563734452546
    0.18409227033985642
    0.7866217402158342
    0.8023851737037745
    8.892207358659476E-4
    0.8614310541417136
    0.6907363995600082
    0.8974247558057734
    0.4294464665985942
    0.19879131710939557
    
    Process completed.
    

    上面输出的完整代码。

    public class Test {
    
       public static void main(String[] args) {
    
        double[] test = new double[10];
    
        fillWithRandomNumbers(test);
    
    
       }
    
    
    
       public static void fillWithRandomNumbers(double[] values){
    
        double[] numbers = new double[values.length];
    
        for(int i = 0 ; i < numbers.length ; i++){
    
        numbers[i] = Math.random();
        values = numbers;
        System.out.println(values[i]);
    
        }
    
     }
    
    
    }
    

    我的问题是这怎么可能?因为在注释中,它指出数组内容不能通过在数组之间直接赋值来复制。如果我没弄错的话,这也适用于c。

    我的解决方案对吗?我只想知道为什么会这样?

    3 回复  |  直到 7 年前
        1
  •  1
  •   David Conrad    7 年前

    分配数组

    values = numbers;
    

    会导致变量 values 引用数组 numbers ,即,它复制引用。

    但是,变量 价值观 是方法的参数,它将超出范围。所以指定的引用将被丢弃。Java是一种严格意义上的值传递语言。当将对数组的引用传递给方法时,该引用的值(本质上是指针)将按值传递给该方法。所以在顶部的原始代码中,调用者的数组将保持不变,新的随机数数组(由 二者都 这个 价值观 数字 变量刚好在方法完成之前,但没有被后面的任何东西指向)将成为垃圾,并将被垃圾收集和丢失。

    如果希望保留带有随机数的新数组,请从方法中返回该数组。另一方面,如果希望更新调用方的数组,则可以 能够 从中复制每个项目 数字 回到 价值观 ,但是在 价值观 首先(然后不需要 数字 数组):

    for (int i = 0; i < values.length; i++) {
        values[i] = Math.random();
    }
    

    方法的名称, fillWithRandomNumbers ,确实表明后一个操作是调用方所希望和期望的。

    另见 Is Java “pass-by-reference” or “pass-by-value”?

        2
  •  0
  •   Eddie D    7 年前

    你不是在复制数组。你只是引用了内存中的同一个对象。想象一下如果你有一个数组 x= [1 , 2, 3, 4]; 你说 y = x ; y x 都指向内存中相同的空间。所以如果我在 X ,它将更改 Y . 没有副本,而是同一个对象。如果我给 X 它将反映在 Y .

    double[] x = new double[10];

    double[] y = x;

    x[0] = 2.0;

    x[0] == y[0] //Will be true

    double[] numbers = new double[values.length];
    
    for(int i = 0 ; i < numbers.length ; i++)
    {
    
      numbers[i] = Math.random();
      values[i] = numbers[i];
    }
    
        3
  •  0
  •   Nemo    7 年前

    你的笔记上写着:

    在Java中,赋值运算符可以用来复制基元数据类型变量,但不复制数组。

    此注释的意思是,不能使用赋值运算符对另一个数组进行深度复制。赋值运算符所做的是生成一个浅拷贝,而不是一个深拷贝。什么是浅拷贝和深拷贝?所有的数据都存在于内存中。当我们创建数组时 x ,它被分配了一个内存位置,比如 0x1000 (地点无关紧要)。如果我们取另一个变量 y 然后分配它 X : (y = x) ,它不会复制中的所有值 X ,它会复制该内存位置 0x1000 . 所以现在 X Y 请参阅内存中的同一位置。这叫做浅拷贝。如果我们在 x: (x[3] = 4) , Y 也收到了那笔钱( System.out.println(y[3]) / / 4!.Y不是独立副本。当我们复制原语时,我们得到的是变量表示的值,而不是它的内存位置。 前任:

    x = 5;
    y = x;
    y = 2;
    // x equals 5 and y equals 2. changing the value of y did not change the value of x!
    

    如果你想做一个深度复制,你可以这样做:

    for(int i=0; i < numbers.length; i++){
        numbers[i] = Math.random();
        values[i] = numbers[i];
    }
    

    现在如果你改变一个数值,它不会改变一个数值。 前任:

    System.out.println(numbers[0]) // 0.5879563734452546
    numbers[0] = 1.2;
    System.out.println(values[0]) // 0.5879563734452546