由传值传引用引发的问题 (Java)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了由传值传引用引发的问题 (Java)相关的知识,希望对你有一定的参考价值。

最近在读《算法导论》,在尝试自己实现归并排序时,发现了一个很奇怪的问题。

为了能够专注于问题,下面使用一段重新编写的能够重现问题的代码。可以尝试运行一下。

 1 public class Main
 2 {
 3  public static void main(String[] args)
 4  {
 5   int[] tmp = {4, 5, 6};
 6   Test.print(tmp);
 7   Test.test(tmp);
 8   Test.print(tmp);
 9  }
10 }
11 class Test {
12  public static void test(int[] src) {
13   int[] out = {1, 2, 3};
14   print(out);
15   src = out;
16   print(src);
17  }
18  public static void print(int[] src) {
19   for(int i : src) {
20    System.out.print(i + "\t");
21   }
22   System.out.println();
23  }
24 }

之前有听说Java是传引用的,且在上述例子中,若将test中的 src = out 改为数组逐元素复制,则最后一行输出将会变为 4 5 6 ,因而一开始并没有想到这方面的问题。然而,拿着这段代码问一位学长时(在此特别感谢符学长),得到答复称Java为传值。于是当时就迷糊了,决定对此详细了解一番。

经过查阅相关资料,了解到Java在传参数时是复制指针,但不进行进一步复制。那么,在执行上述代码的第七行时,应当发生了这些:

  1. Java复制tmp变量的指针,将复制过的指针作为src交由test方法使用。注意,此时tmp与src指向同一个对象,但它们并不是同一个指针。
  2. 程序一路执行到第十六行,这时src的值(地址)被out替代。
  3. 执行到第十七行时,由于此时的src是原先的out,故打印出1 2 3。
  4. test方法执行完毕,src被销毁。

在以上过程中,由于被改变的是tmp的引用副本(即src),故tmp所指向的对象并未发生任何改变。原先的src与out所指向的对象已经失去所有指向其自身的指针,即将在不久后被销毁。而在数组逐元素复制中,src虽然是一个副本,但针对其所指向的对象所作的修改只依赖于指针所指向的对象而非指针本身,故此修改能够反映到tmp中。

参考文章:java中的经典问题:传值与传引用

另外最近成功用VPS建了个独立的博客,点击这里进入

以上是关于由传值传引用引发的问题 (Java)的主要内容,如果未能解决你的问题,请参考以下文章

理解C++传值传址引用调用

php函数值传值/地址以及引用的用法

C语言中的值传参和引用传参是指啥?

Java实参和形参与传值和传引用

C# 页面之间传值传参的6种方法

C# URL传值中有一个#符号传不过去