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

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

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


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

        

我个人是真的认为这个问题没有太大的意义,对于这个问题,《Thinking in java》中给出了经典的解释:如果Java是值传递,那么传递的是值的副本。如果Java是引用传递,那么传递的是引用的副本。怎样来理解这句话。废话从不多说,直接看代码走起。

        

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

        上面这张图一画出来应该就很清楚了,实际上在执行 change(str) 方法的时候,change方法的形参str其实变成了main方法中str变量的一个副本。也被分配在栈中,相当于str这个指针(引用)被拷贝了一份。但是它仍然指向Hello World这个字符串。当执行到  str = "World"; 这行代码的时候,实际上是str副本指向了 World这块内存。原来的str并没有变。change(str) 执行完毕之后str副本的生命周期走到尽头……。显然,str指向的仍然是 Hello World。

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

        在这个例子当中,粗略的画出来JVM运行时内存分配的情况,实际上JVM运行时真实场景远远比这要深奥,精妙!有机会我们再一起去探索!


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

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

留言评论

所有回复

暮色妖娆丶

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