您现在的位置是:首页 > 文章 > 别再纠结Java值传递还是引用传递了 网站文章

别再纠结Java值传递还是引用传递了

孙玉超 2019-12-07 14:25:36 0 评论 2252 浏览 0 收藏 0


前言:不要盲目相信网上的博客教程,我更建议自己动手分析代码!

        

我个人是真的认为这个问题没有太大的意义,为什么专门写一篇文章呢?网上很多人拿这段代码来说 Java 值传递和引用传递,众说风云。其实是什么传递并不重要,重要的是我们应该清楚在代码执行过程中,内存中到底发生了什么。对于这个问题,《Thinking in java》中给出了经典的解释:如果Java是值传递,那么传递的是值的副本。如果Java是引用传递,那么传递的是引用的副本。怎样来理解这句话。废话从不多说,直接看代码走起。

        

        代码通俗易懂,定义一个字符型数组arr,一个字符串str。然后分别执行改变对象的方法,结果呢,str(main方法中的,下同)指向的字符串没有变。但是arr的第一个数组元素内容变了。再结合一张内存变化图:


    


        上面这张图一画出来应该就很清楚了,实际上在执行 change(str) 方法的时候,change方法的形参str其实是自己栈帧中一个局部变量,但是它仍然指向Hello World这个字符串。当执行到  str = "World"; 这行代码的时候,实际上是 change(str) 这个方法的栈帧中的局部变量指向了 World这块内存。原来的str并没有变。change(str) 执行完毕之后该方法对应的栈帧出栈,局部变量销毁……。显然,main 方法中的 str 指向的仍然是 Hello World。不受任何影响。

        再来分析执行 changeArr(arr) 的时候,同样这里也产生了一个自己方法独有的栈帧,这个引用指向了 main 方法中 arr 所指向的内存空间。然后,代码中使用 changeArr(arr) 栈帧中的局部变量来改变了线性表(数组)的第一个元素存放的内容。为什么这个就和上面的结果不一样了呢。因为它是真的改变了数组对象中存放的信息,而 change 方法中的 str 只是更换了自己栈帧中变量指向的对象,不影响 main 方法中的那个 str 变量。可以这么理解,这个数组就像一个仓库,里面放了大米,玉米,小米,糯米……arr是一把原配钥匙,changeArr(arr) 中的 arr 变量是后来复制出来的钥匙,但是不管是哪一把钥匙,只要打开了仓库门,取走了仓库里面的货物。那仓库里面的货物就永远的变掉了。(除非你再还回去,事实上这真的可以~~)。接下来到了与上面类似的情形,执行 arr = new char[5]; 这行代码的时候,changeArr(arr) 的栈帧中的变量重新开辟了一块内存空间。(图上面没有画出来,大家可以自己思考!)。这个时候就好比,另外新建了一个仓库,安排了与这把钥匙匹配的锁,至于它怎么操作,放东西进去 取东西出来,和原来的arr指向的那块内存(就是第一个仓库~)完全没有关系。等到 changeArr(arr) 方法执行结束,此方法独有的栈帧出栈,局部变量销毁,但是内存在堆中的那块地址没有销毁,而且被永久的改变了……所以,两行sout输出的结果,应该很显而易见,能理解了吧!

        在这个例子当中,粗略的画出来JVM运行时内存分配的情况,实际上JVM运行时真实场景远远比这要深奥,精妙!可以参考 JVM系列文章。Java工程师进阶之路之JVM系列(六) —— 对象内存布局


转载请注明出处:转载请注明出处

上一篇 : 我的爱情观 下一篇 : 电影《大约在冬季》观后感

留言评论

所有回复

暮色妖娆丶

96年草根站长,2019年7月接触互联网踏入Java开发岗位,喜欢前后端技术。对技术有强烈的渴望,2019年11月正式上线自己的个人博客