Java中的数组是按引用传递还是按值传递?
假设我有一个名为
data
的数组,其中包含某种类型的对象。现在让我们假设我将该数组传递并存储在 A 类中,然后将它传递给 B 类,B 类更改数组的一个条目。 A 类数组的版本会改变吗?如果这是一个基元数组(例如int
),这有关系吗? ArrayLists 呢?
Java 中的一切都是按值传递的。但是,如果您传递的是引用,它就是引用的值。
由于 Java 方法无法进入调用者的堆栈以重新分配变量,因此任何方法调用都不能更改那里的引用(地址)的标识。这就是我们说 Java 不是按引用传递的意思。这与 C++(和类似语言)形成对比,后者在某些情况下允许这样做。
现在让我们看看一些效果。
如果我这样做:
Object[] o = ...
mutateArray(o);
contents之后可以不同,因为所有
mutateArray
需要的是一个数组的地址来改变它的内容。但是,o
的地址将是相同的。如果我这样做:
String x = "foo";
tryToMutateString(x);
x
的地址之后又是一样的。由于字符串是不可变的,这意味着它仍然是"foo"
.
改变一个对象就是改变它的内容(例如成功改变
o
的最后一个元素,或者试图改变“foo”的最后一个字母为'd')。这不应与调用者堆栈中的重新分配 x
或 o
混淆(不可能)。
维基百科关于 通过分享呼叫 的部分可能会提供更多信息。
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));
}
}
像所有其他对象一样,数组是按引用传递的(从技术上讲,您是按值传递引用,但从对象的角度来看,它是按引用传递的)。如果您将一个数组传递给一个方法并且该方法更改了该数组,则调用者将看到更改。如果你想避免修改你的副本,你需要自己复制它。数组包含基元还是对象并不重要。通常,这是您想要的行为,因为每次将它用作参数时,按值传递将涉及不必要地复制(可能很大)数组。
它的要点是——Java 中的一切都通过引用传递,除非它是原始类型。