修改作为方法参数传递的数组

Posted

技术标签:

【中文标题】修改作为方法参数传递的数组【英文标题】:Modify an array passed as a method-parameter 【发布时间】:2011-10-31 01:23:10 【问题描述】:

假设我有一个 int 数组并且我想修改它。我知道我不能将新数组分配给作为参数传递的数组:

public static void main(String[] args)

    int[] temp_array = 1;
    method(temp_array);
    System.out.println(temp_array[0]); // prints 1

public static void method(int[] n)

    n = new int[]2;

虽然我可以修改它:

public static void main(String[] args)

    int[] temp_array = 1;
    method(temp_array);
    System.out.println(temp_array[0]); // prints 2

public static void method(int[] n)

    n[0] = 2;

然后,我尝试将任意数组分配给使用clone()作为参数传递的数组:

public static void main(String[] args)

    int[] temp_array = 1;
    method(temp_array);
    System.out.println(temp_array[0]); // prints 1 ?!

public static void method(int[] n)

    int[] temp = new int[]2;
    n = temp.clone();

现在,我想知道为什么它在上一个示例中打印 1 而我只是使用 clone() 复制数组,它只是复制值而不是引用。你能帮我解释一下吗?


编辑: 有没有办法在不更改引用的情况下将数组复制到对象?我的意思是让最后一个例子打印2

【问题讨论】:

【参考方案1】:

您的示例 1 和 3 在问题的上下文中几乎相同 - 您正在尝试为 n 分配一个新值(这是对按值传递的数组的引用)。

克隆temp 数组的事实并不重要——它所做的只是创建temp 的副本,然后将其分配给n

为了将值复制到传递给method 方法的数组中,您可能需要查看:System.arraycopy

当然,这一切都取决于您的 n 数组的大小以及您在 method 方法中创建的数组。

假设它们的长度相同,例如,你会这样做:

public static void main(String[] args)

    int[] temp_array = 1;
    method(temp_array);
    System.out.println(temp_array[0]);

public static void method(int[] n)

    int[] temp = new int[]2;
    System.arraycopy(temp, 0, n, 0, n.length); 
    // or System.arraycopy(temp, 0, n, 0, temp.length) - 
    // since we assumed that n and temp are of the same length

【讨论】:

【参考方案2】:

在你的方法中

public static void method(int[] n)

n 是传入数组的另一个名称。它指向与原始数组相同的内存位置,即整数数组。如果您更改存储在该数组中的值之一,则指向它的所有名称都会看到更改。

但是,在实际的方法中

public static void method(int[] n) 
    int[] temp = new int[]2;
    n = temp.clone();

您正在创建一个新数组,然后说“名称 'n' 现在指向这个,另一个数组,而不是传入的那个”。实际上,名称“n”不再是传入数组的名称。

【讨论】:

【参考方案3】:

正如您正确指出的那样,您不能分配给作为参数传递的数组引用。 (或者更准确地说,赋值不会对调用者产生任何影响。)

这是你能做的最好的:

public static void method(int[] n) 
    int[] temp = new int[]2;
    for (int i = 0; i < temp.length; i++) 
        n[i] = temp[i];
    
    // ... or the equivalent using System.arraycopy(...) or some such

当然,这只有在输入数组的大小与您要复制到它的数组的大小相同时才能正常工作。 (你应该如何处理这将是特定于应用程序的......)


为了记录,Java 按值传递数组引用。它不会按值传递数组内容。克隆无助于解决这个问题。 (至少,没有声明的方法签名。)

【讨论】:

那么clone()到底是做什么的呢? 它只是创建对象的副本。但关键是您不需要创建数组的副本。相反,您需要复制其内容。【参考方案4】:

在您的method 方法中,您分配给n 的任何内容都不会改变传入并分配给n 的对象的值。在method 的开头,n 指向一个数组。当您将n 分配给另一个数组时,您只是简单地重新指向了n 指向的数组,并且没有从main 方法更改任何关于temp_array 的内容。

【讨论】:

以上是关于修改作为方法参数传递的数组的主要内容,如果未能解决你的问题,请参考以下文章

C#中数组作为参数传递的问题

数组作为方法参数- 数组作为方法返回值

Java基础——方法

将数组作为 C++ 中方法的 const 参数传递

C语言中,结构体作为函数参数传递,详解?

将内联双精度数组作为方法参数传递