为什么说Java中只有值传递

396 阅读2分钟

值传递/引用传递

程序设计语言将实参传递给方法的方式分为两种:

  • 值传递 :方法接收的是实参值的拷贝,会创建副本。
  • 引用传递 :方法接收的直接是实参所引用的对象在堆中的地址,不会创建副本,对形参的修改将影响到实参。

接下来我们看几个例子来说明为什么Java中是值传递

Example 1

image.png 上面这段代码IDE最终会输出hello, 这样结果应该比较明了了。如果是引用传递的话那么应该是输出world才对。

再来看一个例子

Example 2

image.png 有了上面例子的经验,有的小伙伴可能就说,哎呀,值传递,对象内容不会变得。肯定输出[hello, world]
这样想的小伙伴还是太年轻了,如果跟上一个例子一样,那我还有必要再次举例吗?(城市套路深,我要回农村)

其实这段代码最终输出的是[hello, java]

我们来捋捋,replace方法中把下标为1的值改为了java,那按照第一个例子来说是把strArr副本的数组改变了,应该是不影响原数组的。这也是很多同学认为Java是引用传递的地方。我们知道数组是个对象,其中栈中存的是地址值,堆中存的是具体数据。文章开头说到形参是实参的一份拷贝,那么replace的形参其实是栈中的数组地址值的一份拷贝,而不是整个包括堆内容的拷贝。具体来说只是栈中有两个引用地址指向了堆中的数据。所以在replace方法中修改是会影响到原数组的。

接下来看最后一个例子

Example 3

image.png 这段代码稍微有点多,swap方法的预期功能是把两个数组互换,那么最终会怎样输出呢?有些同学可能又拿不准了。其实原理是跟第一个例子一样,swap方法中的str和str1都是拷贝地址,那么两个拷贝互换关我本体啥事呢?所以最终输出的是[hello, world]\n[hello, java]

结论

在Java中方法参数的传递形式是值传递。需要注意的地方是

  1. 在方法中对基本类型的参数进行改变不会影响原数据,因为基本类型的数据是存在栈中的。
  2. 在方法中对引用类型参数的内容进行改变,如改变某个数组下标的值,改变某个对象的属性,这是会影响到原数据的。
  3. 在方法中对引用类型的参数进行**赋值操作**,如引用地址指向其他对象,这不会影响到原数据。