Java 函数调用是传值还是传引用? 从字节码角度来看看!

本文是网友KailunTalk文章的精简版, 他从字节码的角度解释了Java 函数调用中传递参数的方式, 充分体现了一个程序员深度挖掘,了解底层的精神, 原文地址:https://my.oschina.net/kailuncen/blog/915043

1传值还是传地址?

少废话,先看代码:

0?wx_fmt=png

function1会把车的颜色改为blue

function2 创建了一个新的黑色的车car2, 并且把新车赋值给了输入参数car。

继续看测试类TestReference

0?wx_fmt=png


经过process.function1的处理后,输出结果是:

0?wx_fmt=png

这是很容易理解的, 车的颜色从red被改成了blue。

如果修改一下TestReference, 让它去调用process.function2(car) , 会有什么效果呢? 有经验的程序员可能立刻就能给出答案:

0?wx_fmt=png

在main函数中的那个红色的车根本没有受到影响。

为什么会这样呢?  其实在Java函数调用的过程当中,对于对象类型的参数,Java传递的是这个对象引用的copy,   这个引用的copy和原引用都指向堆上的同一个对象。

在function1中, 虽然使用的是原有引用的copy,但是操作的却是堆中的对象, 于是把这个颜色值改成了blue .

在function2中把这个copy指向了新对象 car2, 那main函数中原有的引用呢? 还是指向堆中的老的对象, 所以没有改变。

2如何实现函数调用

理解到这里,一般来说就够了,但是对于一个刨根问底人,肯定要继续挖掘一下,深入到字节码层次去看看。

首先得理解一下JVM是怎么实现函数调用的, 其实也很简单,JVM把每个函数都封装成一个叫做“帧(Frame)”的东西, 在这个Frame当中,最重要的两个东西就是局部变量表和操作数栈。

0?wx_fmt=png

Java 的计算都是基于栈, 在函数执行过程中会不停地入栈、出栈,计算。 有些中间结果和局部变量就会暂时存放到局部变量表中。

那当main函数调用function2的时候会是什么状况呢?

首先,main函数的Frame 会作为一个元素被压入JVM的栈中(又是栈! 所以函数帧通常称为栈帧), function2的栈帧也会作为一个元素压入栈中:

0?wx_fmt=png

执行完function2 以后,它的栈帧就会退出,接着执行main函数。

3深入字节码

接下来就有难度了,需要深入字节码了。

先使用javap -verbose TestReference.class , 在输出的结果中能看到main函数的各种信息:

0?wx_fmt=png

(点击看大图)

虽然很长,但每行字节码后面有注释, 能大概看个明白。

第0行:创建Process对象

第7行:astore_1 ,把process对象的引用放到了索引为1的局部变量表中

第8-14行:创建了Car 对象(颜色为red)

第17行:astore_2, 把car对象的引用放到了索引为2的局部变量表中


第25行: aload_1, 把局部变量表中索引为1的对象引用(process对象)放到了操作数栈的栈顶

第26行: aload_2, 又把局部变量表中索引为2的对象引用(car 对象)放到了操作数栈的栈顶

(备注:上面说第x行是为了方便,其实是不正确的,正确的说法是偏移量)

到第26行为止,main函数栈帧是这样的:

0?wx_fmt=png

图中的 prcess ref , car ref 表示对两个对象的引用

可能有人要问了,为什么要把car ref, process ref 放到栈顶呢?

还是那句话,java 是基于栈来执行的,由于function2需要两个参数,一个是this(就是process ref) ,一个是car (car ref) ,所以需要把他们两个家伙放到栈顶,形成新栈帧的时候会把他俩传递过去, 并且把这个两个值从栈中清除。

关键的一步来了, 第27行,调用function2!

Java函数栈变成这个样子了:

0?wx_fmt=png

注意局部变量表, 从main中复制过来两个值,一个是this(process ref) 另外一个就是 car ref。

main 的frame还在,只是我们没画出来。

再看看function2的代码:

0?wx_fmt=png

第0-6 行: 创建了一个新的car 对象(颜色为black), 暂时记做car2 ref

第9行: astore_2 , 把car2 ref 存放到了局部变量表的索引为2的位置

第10行:aload_2,  把car 2 ref 放到了栈顶

第11行: astore_1 , 关键的一行, 把 car2 ref 放到了索引为1的位置, 相当于把传递进来的参数car ref 给覆盖掉了

0?wx_fmt=png

现在请问: 在main 栈帧局部变量表中的 car ref受到影响了吗?

答案肯定是:没有!

当function2 执行完, 从JVM栈中退出,接着执行main frame:

0?wx_fmt=png

car ref 所指向的仍然那个有着red 颜色的对象 ,  没有任何变化 !

这篇文章没有涉及基本类型,实际上也是类似的, 总结一下就是:Java 的参数传递,是通过Copy参数的值来进行的,这个值可能是一个基本类型, 也可能是一个引用。

你看到的只是冰山一角, 更多精彩文章,请移步《码农翻身文章精华

有心得想和大家分享? 欢迎投稿 ! 我的联系方式:微信:liuxinlehan  QQ: 3340792577


码农翻身

用故事讲述技术本质

0?wx_fmt=jpeg

微信号:coderising

内容概要:本文详细介绍了利用二维时域有限差分法(2D FDTD)对光子晶体90度弯曲波导进行数仿真的Matlab代码实现。该仿真方法旨在精确分析光子晶体波导在弯曲结构下的光输特性,揭示其导光机制与缺陷模式的调控原理。资源包含完整的Matlab程序代码,支持对空间网格划分、介电常数分布、边界条件(如PML吸收边界)及光源参数等关键仿真要素的灵活设置与优化,便于用户复现结果并开展深入研究。通过仿真可直观获得光场在波导中的播动态、透射谱特性以及能量损耗情况,为高性能光子器件的设计与优化提供理论依据和技术支持。; 适合人群:具备电磁场理论、光学基础和Matlab编程能力,从事光子学、集成光学或纳米光子器件研究的研究生、科研人员及工程技术开发者。; 使用场景及目标:①学习和掌握FDTD方法在周期性介质(光子晶体)器件仿真中的具体应用流程;②研究90度弯波导的光输性能,分析弯曲损耗来源并探索低损耗结构优化方案;③作为光子集成电路中关键无源器件的设计与教学参考案例,服务于学术研究与工程实践。; 阅读建议:建议结合光子晶体能带理论与FDTD算法基本原理进行系统学习,运行代码时应逐步调整结构参数与仿真设置,观察光场演化和输出结果的变化,以深化对物理现象的理解,并可在此基础上拓展至其他复杂光子结构(如分束器、谐振腔)的仿真分析。
内容概要:本文系统研究了基于共识的捆绑算法(Consensus-Based Bundle Algorithm, CBBA)在多智能体多任务分配中的应用,重点聚焦于远程太空船交会与维修任务中的相对运动规划(RPO)问题。通过构建多航天器协同任务场景,采用Matlab代码实现了CBBA算法的全过程仿真,展示了其在分布式决策框架下高效完成任务分配的能力。研究深入探讨了任务收益建模、路径规划约束、通信延迟与动态重规划等关键环节,验证了CBBA在确保任务分配一致性、避免资源冲突、适应动态环境变化以及优化整体任务效能方面的优越性能,为复杂空间任务中的自主协同提供了可靠的技术路径。; 适合人群:具备控制理论、航天动力学、分布式优化或多智能体系统等相关背景,从事航天任务规划、智能优化算法研究或相关工程实践的研究生、科研人员及航空航天领域工程师。; 使用场景及目标:①为多航天器在轨服务(如交会对接、空间维修)提供高效、鲁棒的分布式任务分配解决方案;②深入理解CBBA算法的核心机制及其在高动态、强约束空间任务中的适应性与优化潜力;③推动分布式人工智能算法在航天工程实际系统中的集成与应用验证。; 阅读建议:建议读者结合提供的Matlab代码,重点剖析任务建模逻辑、收益函数设计、共识迭代过程及收敛性分析模块,通过修改场景参数进行仿真实验,以深化对多智能体协同决策机制与算法性能边界条件的理解。
内容概要:本文研究了一种计及自适应预测修正的微电网模型预测控制(MPC)优化调度方法,并提供了基于Matlab的完整代码实现。该方法融合自适应预测机制与MPC滚动优化框架,有效应对微电网中可再生能源出力波动、负荷需求不确定性等多重挑战,显著提升调度决策的精度与系统鲁棒性。通过构建动态反馈校正机制,实时修正预测模型误差,优化未来时段的运行策略,实现对微电网内部分布式电源、储能系统及可控负荷的协同调控,达成经济性、稳定性与环保性多目标的综合优化。所提方法具有较强的工程实用性与理论价,为现代智能微电网的能量管理系统提供了可靠的技术支撑。; 适合人群:具备电力系统分析、优化控制理论基础及Matlab编程能力的研究生、科研人员,以及从事微电网、智能配电系统、新能源并网等领域技术研发的工程技术人员。; 使用场景及目标:①应用于高校与科研机构开展微电网优化调度算法的仿真研究与性能验证;②服务于电力企业或能源科技公司开发先进能量管理系统(EMS),提升微电网运行效率与可再生能源消纳能力;③作为自动化、电气工程等专业的高级教学案例,帮助学生深入理解MPC在复杂能源系统中的建模、优化与反馈控制全过程。; 阅读建议:建议读者结合Matlab代码逐模块分析算法实现流程,重点掌握预测模型构建、滚动优化求解及反馈修正机制的设计逻辑,可通过调整预测时域、权重系数与扰动场景等参数进行仿真实验,深入理解各环节对系统性能的影响。
内容概要:本文围绕电力系统短期负荷预测问题,深入研究了基于极限学习机(ELM)及其智能优化算法的应用方法,提出并实现了白鲸优化算法(BWO)和鹭鹰优化算法(IBOA)对ELM模型的关键参数进行寻优的技术路径。通过Matlab编程实现,优化后的模型有效提升了预测精度,降低了原始ELM因随机初始化带来的不稳定性和误差波动,增强了模型在面对电力负荷不确定性变化时的泛化能力和鲁棒性。研究系统阐述了ELM的基本原理、两种新型群智能优化算法的搜索机制及其在解决非线性参数优化问题上的优势,并通过实验对比验证了优化模型在均方根误差(RMSE)、平均绝对百分比误差(MAPE)等指标上的显著优越性,为电力系统负荷预测提供了高效可靠的解决方案。; 适合人群:具备电力系统分析、人工智能算法理论基础及Matlab编程能力的高校研究生、科研机构研究人员以及电力公司从事负荷预测、电网调度与能源管理的工程技术人员。; 使用场景及目标:①应用于电网调度中心的短期负荷预测业务,提高预测准确性,保障电力供需平衡;②为智能优化算法在电力工程领域的落地应用提供可复现的技术范例;③支撑电力市场出清、发电计划制定、储能系统配置及需求侧响应等关键决策环节; 阅读建议:建议读者结合提供的Matlab代码进行实践操作,重点理解ELM网络结构搭建、适应度函数设计、优化算法迭代流程及预测结果后处理等关键步骤,通过调整数据集和参数设置,深入掌握模型调优技巧,并尝试将该方法迁移至风电、光伏功率预测等相似时序预测任务中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值