Java到底是值传递还是引用传递?

这虽然是一个老生常谈的问题,但是对于没有深入研究过这块,或者Java基础不牢的同学,还是很难回答得让人满意。

可能很多同学能够很轻松的背出JVM、分布式事务、高并发、秒杀系统、领域模型等高难度问题,但是对于Java基础问题不屑一顾。这种抓大放小的初衷是对的,要是碰到深究基础细节的面试官,就抓瞎了。

今天一灯带你一块深入剖析Java传递的底层原理,看完这篇文章再去面试,面试官肯定要竖起大拇哥夸你:

“小伙子,你是懂Java传递的!”

1. 什么是形参和实参

形参: 就是形式参数,用于定义方法的时候使用的参数,是用来接收调用者传递的参数的。

实参: 就是实际参数,用于调用时传递给方法的参数。实参在传递给别的方法之前是要被预先赋值的。

/*** @author 一灯架构* @apiNote Java传递示例**/
public class Demo {public static void main(String[] args) {String name = "一灯架构"; // 这里的name就是实际参数update(name);System.out.println(name);}// 这里方法参数列表中name就是形式参数private static void update(String name) {// doSomething}}

在Java方法调用的过程中,就是把实参传递给形参,形参的作用域在方法内部。

2. 什么是值传递和引用传递

值传递: 是指在调用方法时,将实际参数拷贝一份传递给方法,这样在方法中修改形式参数时,不会影响到实际参数。

引用传递: 也叫地址传递,是指在调用方法时,将实际参数的地址传递给方法,这样在方法中对形式参数的修改,将影响到实际参数。

也就是说值传递,传递的是副本。引用传递,传递的是实际内存地址。这是两者的本质区别,下面会用到。

3. 测试验证

3.1 基本数据类型验证

先用基本数据类型验证一下:

/*** @author 一灯架构* @apiNote Java传递示例**/
public class Demo {public static void main(String[] args) {int count = 0;update(count);System.out.println("main方法中count:" + count);}private static void update(int count) {count++;System.out.println("update方法中count:" + count);}}

输出结果:

update方法中count:1
main方法中count:0

可以看到虽然update方法修改了形参count的值,但是main方法中实参count的值并没有变,但是为什么没有变?我们深究一下底层原理。

我们都知道Java基本数据类型是存储在虚拟机栈内存中,栈中存放着栈帧,方法调用的过程,就是栈帧在栈中入栈、出栈的过程。

当执行main方法的时候,就往虚拟机栈中压入一个栈帧,栈帧中存储的局部变量信息是count=0。

当执行update方法的时候,再往虚拟机栈中压入一个栈帧,栈帧中存储的局部变量信息是count=0。

修改update栈帧中数据,显然不会影响到main方法栈帧的数据。

3.2 引用类型验证

再用引用类型数据验证一下:

/*** @author 一灯架构* @apiNote Java传递示例**/
public class Demo {public static void main(String[] args) {User user = new User();user.setId(0);update(user);System.out.println("main方法中user:" + user);}private static void update(User user) {user = new User();user.setId(1);System.out.println("update方法中user:" + user);}}

输出结果:

update方法中user:User(id=1)
main方法中user:User(id=0)

由代码得知,update方法中重新初始化了user对象,并重新赋值,并不影响main方法中实参数据。

当执行main方法时,会在堆内存中开辟一块内存,在栈内存中压入一个栈帧,栈帧中存储一个引用,指向堆内存中的地址。

当调用update方法时,会把main方法的栈帧拷贝一份,再压入栈内存中,指向同一个堆内存地址。

当执行update方法,重新初始化user对象,并重新赋值的时候。会在堆内存中再开辟一块内存,再把栈内存中update栈帧指向新的堆内存地址,并修改新的堆内存中的数据。

从这里可以看出是值传递,修改了形参里面数据,实参并没有跟着变化。

3.3 同一地址的引用类型验证

/*** @author 一灯架构* @apiNote Java传递示例**/
public class Demo {public static void main(String[] args) {User user = new User();user.setId(0);update(user);System.out.println("main方法中user:" + user);}private static void update(User user) {user.setId(1);System.out.println("update方法中user:" + user);}}

输出结果:

update方法中user:User(id=1)
main方法中user:User(id=1)

可以看出update方法修改user对象的属性,main方法中user对象也跟着变了。

这是不是说明Java支持引用传递呢?

并不是。这里在参数传递的过程中,只是把实参的地址拷贝了一份传递给形参,update方法中只修改了参数地址里面的内容,并没有对形参本身进行修改。

4. 总结

经过上述分析,Java参数传递中,不管传递的是基本数据类型还是引用类型,都是值传递

当传递基本数据类型,比如原始类型(int、long、char等)、包装类型(Integer、Long、String等),实参和形参都是存储在不同的栈帧内,修改形参的栈帧数据,不会影响实参的数据。

当传参的引用类型,形参和实参指向同一个地址的时候,修改形参地址的内容,会影响到实参。当形参和实参指向不同的地址的时候,修改形参地址的内容,并不会影响到实参。

死磕面试系列,Java到底是值传递还是引用传递?相关推荐

  1. 面试:Java 到底是值传递还是引用传递?

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | Intopass 来源 | zhihu.com ...

  2. 吊打面试官 | Java到底是值传递还是引用传递

    HI ! 我是小小,我们又见面了,今天是本周的第六篇,这篇主要讲解关于Java到底是值传递还是引用传递. 先说答案 答案为值传递 答案解释 先说一下值传递和引用传递的概念和区别 值传递:是指在调用函数 ...

  3. 面试官:兄弟,说说Java到底是值传递还是引用传递

    二哥,好久没更新面试官系列的文章了啊,真的是把我等着急了,所以特意过来催催.我最近一段时间在找工作,能从二哥的文章中学到一点就多一点信心啊! 说句实在话,离读者 trust you 发给我这段信息已经 ...

  4. 面试官:Java 到底是值传递还是引用传递?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:Intopass 来源:知乎,zhihu.com/q ...

  5. Java面试之到底值传递和引用传递???

    值传递和引用传递 举例 /*** 值传递和引用传递*/ class Person {private Integer id;private String personName;public Person ...

  6. 死磕数据库系列(二十六):MySQL 高可用之单主、双主模型组复制配置实践

    点关注公众号,回复"1024"获取2TB学习资源! 前面我们学习:MySQL 高可用之组复制(MGR)技术的相关原理知识,今天我将详细的为大家介绍 MySQL 高可用技术组复制的单 ...

  7. 死磕数据库系列(二十):MySQL 数据库 DDL、DML、DQL、DCL 语言理论与实践(sql 8.0 版)...

    点关注公众号,回复"1024"获取2TB学习资源! 今天,民工哥带大家一起来学习一下 MySQL 数据库的 DDL.DML.DQL.DCL 这几种语言的理论知识与实践.如有帮助,请 ...

  8. 死磕数据库系列(三十五):MySQL 数据库性能监控

    点关注公众号,回复"1024"获取2TB学习资源! 前面给大家介绍了:MySQL 性能分析与相关工具的使用.今天我将详细的为大家介绍 MySQL 性能监控的相关知识,希望大家能够从 ...

  9. 多图证明,Java到底是值传递还是引用传递?

    作者 | 王磊 来源 | Java中文社群(ID:javacn666) 转载请联系授权(微信ID:GG_Stone) 开篇先来曝答案,在 Java 语言中,本质只有值传递,而无引用传递,解释和证明详见 ...

最新文章

  1. VMware Horizon7的部署(接上期校园网络建设)《二》
  2. 大疆手持云台和华为mate20_告别手残,华为Mate30与大疆手持云台拍照真香
  3. C java new_你还在new对象吗?Java8通用Builder了解一下?
  4. python字符串说法错误的是_【单选题】关于Python字符串的表示方法,下列说法错误的是: A. 字符串是字符的序列表示,只能由...
  5. 删除用户账号的命令 mysql_【Mysql】常用指令之——用户操作(创建,授权,修改,删除)...
  6. linux思考与实验答案,linux课后习题答案教材课后习题参考答案
  7. NSCalendar日历
  8. linux测试at命令,linux at命令:(定时执行脚本)
  9. 网络工程师的机会在哪里
  10. matlab四宫格画图_科学网—Matlab画图(一):生成高质量的供发表和展示用的图 - 周建锋的博文...
  11. Debian9系统上 基于Qt5.12.1 开发的QML界面程序 无法输入中文
  12. Matlab绘制树形图
  13. 【AE】2 ICommand和ITool
  14. XMLHTTP的ReadyState与Statu详解
  15. 一个IOS音乐播放器源码
  16. javamail 读取邮箱邮件并下载附件
  17. HTML5系列代码:为文字设置深灰色阴影
  18. 关于现时构型的ds和初始构型的dS
  19. 谈谈ali与Google的Java开发规范
  20. qt for android开发百度地图(一步步带图详解)

热门文章

  1. android属性动画不流畅,Android动画之属性动画
  2. 【PS功能学习】13:从昏暗到光明(调色二)
  3. 无废话硬核分享:Linux 基础知识点总结很详细,全的很,吐血奉献
  4. 网络数据包拦截通用技术
  5. Linux 虚拟内存 交换空间
  6. docker安装tomcat8并实现目录映射端口映射
  7. linux有端口找不到进程,linux查看端口和进程
  8. 浅析云卡通的美食城应用前景
  9. 看不见硝烟的战场 人工智能如何运用到网络作战?
  10. 《理财有道》读书心得