Java中的数组是按引用传递还是按值传递?

5

Java中的数组是按引用传递还是按值传递?

假设我有一个名为data的数组,其中包含某种类型的对象。现在让我们假设我将该数组传递并存储在类A中,然后将其传递到类B中,并且类B更改了数组中的一个条目。类A版本的数组会改变吗?如果这是原语类型的数组(例如int),会有什么影响吗?那么ArrayList呢?


9
为什么不直接测试一下呢?如果你已经测试过了,你得出了什么结论?(顺便说一句,这不是我的投票否决) - Hovercraft Full Of Eels
1
我对downvote没有任何问题 :-). 我同意这是一个非常基础的问题,但是在我职业生涯早期,我也曾经问过自己。Sun(现在是Oracle)的官方Java教程通常要么非常通用,要么非常高级,如果Java是你学习的第一种编程语言。 - Petro Semeniuk
4个回答

9

Java中的所有内容都是按值传递的。但是,如果您传递引用,则是引用的值。

由于Java方法无法访问调用者的堆栈以重新分配变量,因此任何方法调用都无法更改引用(地址)的标识符。这就是我们所说的Java不是按引用传递的含义。这与C ++(以及类似语言)形成对比,后者在某些情况下允许这样做。

现在让我们看一些效果。

如果我执行以下操作:

Object[] o = ...
mutateArray(o);

接下来的内容可能会有所不同,因为mutateArray只需要一个数组的地址就可以改变其内容。但是o的地址将保持不变。如果我执行:

String x = "foo";
tryToMutateString(x);
x的地址在此之后仍然相同。由于字符串是不可变的,这意味着它仍将是"foo"
改变一个对象的内容就是改变它的内容(例如成功地更改o的最后一个元素,或尝试将“foo”的最后一个字母更改为'd')。这不应与在调用者的堆栈中重新分配xo混淆(不可能)。
维基百科关于共享调用的部分可能会有所启示。

0

Java中的所有内容都是按值传递的,这很令人困惑,因为当我们在Java中创建一个对象或数组时,我们将该对象的地址存储在变量中(而不是对象本身)。因此,当我们将该变量传递给一个方法时,该方法会获取该地址(即一个值)并将其存储在其本地变量中。对本地变量所做的任何更改都不会反映在原始变量中。

然而,我们可以使用包含对象地址的本地变量来访问对象的字段和方法。同样,数组也是一个对象。

以下是如何利用所有这些知识:

package newStart;

import java.util.Arrays;

public class JavaIsAlwaysCallByValueArray {


static void swap(int[] a,int[] b )
{
    int[] temp=a;
    a=b;
    b=temp; //all this is doing is swapping the address of local variables 
of this method which will not be reflected in main method 
}

static void swapThisWay(int[] a,int b[])
{
    int[] temp=new int[b.length];
    for(int i=0;i<a.length;i++)  //here we are using this variable to 
access field of array object
        temp[i]=a[i];
    for(int i=0;i<b.length;i++)
    {
        a[i]=b[i];
    }
    for(int i=0;i<b.length;i++)
        b[i]=temp[i];
    `enter code here`}

public static void main(String args[])
{
    int a1[]= {1,2,4,6,8};
    int a2[]= {6,5,3,8,9};
    swap(a1,a2);
    System.out.println("just swap \na1 : "+Arrays.toString(a1)+"\na2 : 
"+Arrays.toString(a2));
    swapThisWay(a1,a2);
    System.out.println("Now \na1 : "+Arrays.toString(a1)+"\na2 : 
"+Arrays.toString(a2));
}

}

-5

数组和其他对象一样,是按引用传递的(从技术上讲,你是通过值传递引用,但从对象的角度来看,它是按引用传递的)。如果你将一个数组传递给一个方法,并且该方法更改了数组,调用者将看到这些更改。如果你想避免副本被修改,你需要自己复制它。无论数组包含原始类型还是对象,都没有关系。通常,这是你想要的行为,因为按值传递会在每次使用它作为参数时不必要地复制(可能很大的)数组。


-5

Java的要点是 - 除非它是原始类型,否则Java中的所有内容都是按引用传递的。


我要给这个点个踩,因为已经有两个人说过了,而且这个说法最多也只能算是误导。至少Petro解释了术语争议。 - Matthew Flaschen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接