【一看就懂】为什么说Java没有引用传递 !

写在最前

【根目录】Java编程思想【读书笔记】【不断更新…】


前言

本文想说清的问题有两个:

1.引用传递并不是传递引用
2.Java没有引用传递!只有值传递!

  • 在【Java编程思想】一书中的第二章的最下方有这么一行小字,记录着作者认同Java只有值传递的观点;以及提到了“引用”一词,只是为了贴近C++的程序员,了解Java对象的操作的一个概念。
    在这里插入图片描述
  • 本文想表达的是,并不是使用引用操纵对象,或者传递(拷贝)了引用地址,就是引用传递了,依旧是值拷贝,是值传递!

值传递和引用传递的区别

  • Java值传递就是当前方法调用新的方法的时候,入栈了一个新的栈帧对应被调用的方法,然后将实参进行值拷贝,拷贝到新栈帧中的局部变量表进行存储(注意拷贝的可以是基本类型的值,也可以是引用类型的引用地址
  • 什么是引用传递? 引用传递绝对不是传递地址这么简单!!不要被大学C语言老师给骗了!,因为Java中没有引用传递,因此用C++来举例。
  • 引用传递,实参通过引用传递,传递给形参的时候,形参其实相当于实参的一个别名,形参没有自己的存储数据的内存地址,可以说他就是实参的一个替身
  • 当对形参操作的时候,其实就相当于对实参进行了操作!实参是会受到影响的!

有必要搞清楚什么是引用传递

引用传递绝对不是传递地址这么简单!
从C++来看,使用引用传递时,形参其实就是实参的一个别名,其实实参和形参是同一个变量。

  • 引用变量是变量的另一个别名,它没有自己的存储数据的内存位置,它访问的是另一个变量的内存位置。

  • 对引用变量作出的任何更改,实际上都是对它所引用的变量内存位置中存储数据的更改。

  • 当使用引用变量作为形参时,它将变为实参列表中相应变量的别名,对形参进行的任何更改都将真正更改正在调用它的函数中的变量。当以这种方式将数据传递给形参时,该实参被称为按引用传递


引用传递和传递引用的区别

  • 话先说明白:传递引用其实是值传递,只不过复制的是对象的引用地址罢了
  • 值传递,单纯的值拷贝,非常的纯粹。有些人会有疑惑:“为什么传递引用对象的时候,形参发生改变,会造成实参改变,这也算值传递?”,下面会说清楚这件事!)·
  • 引用传递的话:形参就是实参的一个别名罢了,两个参数其实就只有实参一个变量 ,形参的操作时会直接影响实参的。

为什么Java传引用对象是值传递,形参改变会影响到实参?

(1)先说一般的引用对象

  • 首先要知道对象实体是在堆中创建的,栈中的变量保存的是对象的引用地址(不给对象重写toString()方法的时候输出对象,打印出来的信息可以看到。)
  • Java中传递引用对象,是将引用变量中存的对象的引用地址进行值拷贝!。也就是从一个栈帧,复制到其调用的栈帧中的局部变量表的形参下进行存储!
  • 这个时候两个引用变量存的是同一个堆中对象的引用地址(注意是堆中的同一个唯一的对象!),这个时候形参对其进行修改,那么实参指向的也是这个唯一的对象,当然能够感知到形参对其进行修改了。
  • 但是这确实是值拷贝!因为实参的引用地址原封不动的拷贝到了形参下进行存储!只不过形参改变了这个地址指向的值被实参感知到了。这可不影响值传递的原则定义

(2)再说String

  • 那么为什么传String对象也是传递引用,形参修改了,实参不会影响???
  • 因为String是final修饰的!
  • 比如形参X存储的是"hello"字符串的地址aaaaa,并将地址传递给了形参Y,那么Y中一开始存储的的确是aaaaa这个地址。
  • 只不过,如果Y对值进行修改,Java会在堆中的字符串常量池中,将另外的地址赋值给Y。但是原先的"hello"的地址是不会改变的!X依旧指向他!只不过Y因为修改了值,存储了一个新的引用地址bbbbb。
  • 这个时候Y对值的修改,当然是不会影响到X存储的引用地址啦!因为是值拷贝嘛!

如何证明Java中传递引用是“值传递”,而不是“引用传递”?

先在心中默念几遍,如果是引用传递,形参就是实参,只不过形参取了个别名罢了,形参实参是一个东西!

  • 好的现在我们开始试验:

  • Step 1.假设这里有一个再简单不过的Student对象(其中有构造函数getter和setter以及toString()方法):
    在这里插入图片描述

  • Step 2.下面这段代码证明了Java中的传递引用不是引用传递
    在这里插入图片描述
    我们看看输出:
    在这里插入图片描述

解释一下:

  • 因为如果是引用传递的话,形参就是实参,只不过取了个别名,俩玩意儿是同一东西,那么在change方法中new一个新的Student对象,并存在形参中,这个操作会改变实参中存储的值也变成新new的对象的引用地址!
  • 然后实际上我们发现并非如此!实参保存的引用地址指向的对象还是原先的对象并没有发生改变!
  • 跟String引用对象传参是一样的道理!实参指向的是一个aaaaa的引用地址,传给了形参,可是形参new了个新的对象,并将新对象的引用地址bbbbb存到了形参中。这并不会影响到实参中存储的aaaaa地址,因为Java中只有值传递,是最纯粹的值拷贝!不是别名不是分身!

【我尽量用最直白的话来讲述出我对这个问题的理解;有哪里讲错了可以提出,我们共同进步】



————— END —————




评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值