当我拿一个数组时,就像这样:
int anArray[] = new int[5];
//initialize to 0
doStuff(anArray);
//inside doStuff
anArray[3] = 731;
//passes back to main
System.out.println(anArray[3]); // outputs 731
这不是参考通过吗?是什么给了什么?
答案 0 :(得分:5)
像数组这样的引用类型仍被视为按值传递,因为您传递了引用值的副本。请注意,您没有传入实际的引用句柄。也就是说,你的doStuff方法不能改变对anArray的引用,就像传递引用语义一样。一个例子应该有助于理解差异:
int anArray[] = new int[] { 99, 100};
doStuff(anArray);
...
//inside doStuff
anArray = new int[] { 68, 69};
...
// back in anArray's original scope
System.out.println(anArray[1]); // still outputs 100, not 69
答案 1 :(得分:2)
您的数组是一个存在于堆上的对象(内存中的某个位置)。它存在于那里,只要程序中至少有一个活动引用指向它。
您可以将引用视为指向数组的链接或指针。引用通常只是一个小值,它告诉程序如何在其内存地址访问您关心的对象。假设引用指向内存地址100.当您将引用传递给方法时,它将按值传递,因此该方法获取引用的副本。新值100进入方法。
当您尝试在该方法中对数组执行某些操作时,将考虑引用的值并用于访问内存中的对象。所以,我们查找地址100,得到我们关心的对象并完成。
一旦退出方法,方法内部引用的值就会消失(它是一个局部变量),但在方法之外你仍然有一个引用的副本,你仍然可以使用它来访问地址100你的对象是。
因此,我们只是通过引用获得对象的感知,而当对象总是在内存中的相同位置时,我们只是传递一个被复制的引用值。由于副本具有与方法外部相同的值地址,因此我们可以访问同一对象。
答案 2 :(得分:1)
您正在修改可变对象的状态,在本例中是一个数组。但是,当您尝试此代码时,您会发现doStuff函数获取通过值传入的数组:
public class try1
{
static void doStuff(int[] anArray)
{
anArray = new int[] {
5, 6, 7
};
System.out.println(java.util.Arrays.toString(anArray));
}
public static void main(String[] args)
{
int[] anArray = new int[] {
0, 1, 2
};
System.out.println(java.util.Arrays.toString(anArray));
doStuff(anArray);
System.out.println(java.util.Arrays.toString(anArray));
}
}
答案 3 :(得分:0)
Java是按值传递的。周期。
方法得到的是变量内容的值的副本,总是如此。这适用于基元和对象。在对象的情况下,变量的值是一个地址,告诉JVM如何在堆内存中找到对象。
根据您的情况,开头的变量anArray
和doStuff
函数内的变量都保持相同的值,告诉JVM如何检索相同的数组(只有一个)记忆。就是这样。
请注意,我甚至不必使用“引用”这个词来给出这个答案......不,在谈论Java时我永远不会使用“指针”这个词。
关于按引用传递vs值的大量讨论是here。