zedgraph 两点之间值_Stack Overflow上188W+程序员都关注的问题:Java到底是值传递还是引用传递?...

bae350d47630332a1980aa17036af488.png 来源: https://juejin.im/post/5df03a7b6fb9a01638079fb3 往期热门文章:
1、往期精选优秀博文都在这里了!2、Dubbo必会的18个面试题!一网打尽!3、后端开发甩锅指南!4、可以提高千倍效率的Java代码小技巧5、ThreadLocal面试六连问,你能Hold住吗?

在逛 Stack Overflow 的时候,发现了一些访问量像阿尔卑斯山一样高的问题,比如说这个:Java 到底是值传递还是引用传递?访问量足足有 188万+,这不得了啊!说明有很多很多的程序员被这个问题困扰过。实话实说吧,我就是其中之一。

来回顾一下提问者的问题:

我一直认为 Java 是按引用传递的,但是我看一些博客上说不是的。我就纳闷了,Java 到底是值传递还是引用传递?值传递和引用传递有什么区别呢?

如果你也曾被这个问题困扰过,或者正在被困扰,就请随我一起来梳理一下问题的答案。打怪进阶喽!

01、值传递和引用传递

什么是值传递,什么是引用传递?我们需要先把这两个定义搞清楚,才能搞清楚 Java 是按值传递还是按引用传递。

值传递(pass by value)是指在调用方法时将实参复制一份传递到方法中,这样当方法对形参进行修改时不会影响到实参。引用传递(pass by reference)是指在调用方法时将实参的地址直接传递到方法中,那么在方法中对形参所进行的修改,将影响到实参。

上面是比较官方的定义,读起来不免生硬。在我看来,值传递和引用传递的关键区别有两点:

1)调用方法时有没有对实参进行复制。

2)方法内对形参的修改会不会影响到实参。

what?值传递和引用传递还没有搞清楚,又来两个新名词:实参和形参。别急,别急。

02、实参和形参

实参和形参理解起来比值传递和引用传递容易的多,前者就好像是一元一次方程,后者就像是一元二次方程。

形参:定义方法名和方法体的时候使用的参数,目的是用来接收调用该方法时传入的参数。实参:在调用有参方法时传入的参数,方法名后面的括号中的参数通常被称为“实参”。

大家应该都写过“hello world”程序了,就像下面这样。

686db5e412253587d658f97439ec0605.png

其中 args 就相当于是形参,而字符串“hello world”就相当于是实参。如果觉得这个例子不容易理解,那再来看一个。

906466d2f65d7df7df7c7a62eecd80c4.png

其中“沉默王二”为实参;有参方法 sop(String name) 中的 name 为形参。形参就好像实参与被调用方法之间的一个桥梁,否则调用者没法传递参数,被调用的方法无法接收参数。

03、基本类型是值传递的

Java 中的数据类型可以分为两种,一种是基本类型,一种是引用类型。我相信大家在看本篇文章之前,就能够达成这样一个共识:基本类型是值传递的。这一点毫无疑问。

1016ba21bed32936af1e4506f0da7252.png

上面这段代码中,sop() 方法的实参 age 为 18,尽管 sop() 方法的形参被修改为 28,但并不会影响实参的值。这一点可以从输出结果中加以证明。

b10f5601725872cb4820c63d22935e4a.png

具体的执行过程如下图所示。

906018ea9f89328f80d573eee8cfbda2.png

04、引用类型是值传递吗?

大家之所以不确定 Java 是值传递的还是引用传递的,原因就出在这个引用类型上面。单从字面的意思上就容易搞混:引用类型不是引用传递难道还是值传递?

5b07162fc492bb34656483bfa25f817d.png

在 main() 方法中,我们通过 new 关键字创建了一个对象 cmower,并将其 name 属性设置为“沉默王二”;然后将实参 cmower 传递给 sop() 方法,在 sop() 方法中将形参 cmower 的 name 属性修改为“沉默王三”。输出结果是什么样子呢?

b861850019d2a6e67236748220a118b3.png

呀!实参 cmower 的属性 name 竟然不是“沉默王二”而是“沉默王三”了!看看,看看,Java 不是值传递吧?

别急别急。我们在 main 方法中追加几行代码。

935ddb26a84b369c2d3e2d7fe5d774e3.png

old == cmower 会是 true 还是 false 呢?闭上眼睛想一想。如果实在是想不出,抛一枚硬币吧,反正不是 true 就是 false。假如引用类型是引用传递的,根据引用传递的定义(形参的修改将会影响到实参),那么结果一定就是 false。

我们来看一下输出结果:

b32fee3d51f1d22edf8a3238e266f979.png

true?开什么玩笑?

不好意思,没有开玩笑。Java 的确是值传递的。只不过,引用类型在调用有参方法的时候,传递的是对象的引用,并不是对象本身。而对象的引用在传递的过程中并没有发生改变,虽然对象本身发生了变化。可以通过下面这幅图感受一下。

1923b08981d6b10906587e9742111fbb.png

这下理解了吧?

05、总结

来看下面这段代码。

479214a1e5538a286936468700bfa62c.png

age 是基本类型,所以值就直接保存在变量中;而 name 是引用类型,变量中保存的只是对象的内存地址,这种变量一般称之为对象的引用。

基本类型作为参数被传递时肯定是值传递;引用类型作为参数被传递时也是值传递,只不过“值”为对应的引用。

往期热门文章:

1、历史文章分类导读列表!精选优秀博文都在这里了!2、Mybatis的这些坑!把我坑惨了!3、MySQL 用 limit 为什么会影响性能?4、ThreadLocal面试六连问,你能Hold住吗?5、是时候扔掉 Postman 了,试试 IntelliJ IDEA 自带的高能神器!6、2年Java,蚂蚁一面,卒!7、8种最坑的SQL错误用法,第一个就很坑?8、假如曹操是一名程序员,会发生什么

9、IDEA的这几个调试的骚操作,用了都说爽!

10、MySQL用得好好的,为啥非要转ES? 2b6c8d45946c2fe4bf9bec57f8c3f10c.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值