有人可以解释一下java是如何通过值传递的

时间:2011-08-29 02:33:40

标签: java pass-by-reference pass-by-value

当我拿一个数组时,就像这样:

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

这不是参考通过吗?是什么给了什么?

4 个答案:

答案 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如何在堆内存中找到对象。

根据您的情况,开头的变量anArraydoStuff函数内的变量都保持相同的值,告诉JVM如何检索相同的数组(只有一个)记忆。就是这样。

请注意,我甚至不必使用“引用”这个词来给出这个答案......不,在谈论Java时我永远不会使用“指针”这个词。

关于按引用传递vs值的大量讨论是here