结论:
Java中参数传递是按值传递(call by value)的:
1.当实参为基本数据类型时,传递的是一份字面量值的拷贝。
2.当实参为引用数据类型时,传递的是对象的地址。
正文部分:
简单描述概念:
值传递:是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
引用传递:是指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
形式参数:Java中定义方法名和方法体所使用的参数,用来接收调用方法时传入的参数。
实际参数:Java中调用有参方法时,调用方法右边所传入的参数。
在本文中,除了了解什么是形参和实参以外,还需要了解Java中的赋值操作,这和理清传递关系有着密切关系。
赋值:赋值是用等号运算符(=)进行的。它的意思是“取得右边的值,把它复制到左边”。右边的值可以是任何常数、变量或者表达式,只要能产生一个值就行。但左边的值必须是一个明确的、已命名的变量的引用。String类型的形参在方法中改变字符串,实际上就是将一个新的String对象赋值给了引用。
了解了基本概念后,看一些传递的实验:
实验1:一个值为0的int类型在方法内被+1,但回到主函数后打印却仍然为0。
![](https://img.haomeiwen.com/i7582099/c1697fc40ab9d678.png)
实验2:一个String类型在方法内被修改,回到main函数中打印却没有变化。
![](https://img.haomeiwen.com/i7582099/8483c16937e46602.png)
实验3:changeName方法内改变了传入user对象的属性,回到主方法后打印发现user对象有变化。
![](https://img.haomeiwen.com/i7582099/744fbf8b42f036f4.png)
实验4:user对象传入changeName方法后,重新new了一个对象,并设置属性。回到主方法后发现打印出来的还是原来的user。
![](https://img.haomeiwen.com/i7582099/04f9922c093a45b7.png)
分析:
首先来看一下值传递和引用传递的区别的重点:
![](https://img.haomeiwen.com/i7582099/5c467abde53739c3.jpg)
实验1:
add()方法经过i++,打印出来为1,但回到main()内,仍然是0。在函数中对基本数据类型形参的修改没有影响到实参,看起来好像是值传递。
实验2:
在changeName()中把name改成了"lcc",但回到main()内仍然是"yby"。看起来我们修改了String的值,但实际上name引用其实被指向了新的String对象"lcc",因此方法内对形参引用的重新指向同样也没有影响到实参。看起来也好像是值传递。
实验3:
在changeName()内改变了形参user的属性,回到main()中打印实参user时发现同样被改变了。这里看起来好像是引用传递,但实际上这个方法内和其他测试不同,本次测试没有改变形参引用的指向,而是改变了引用指向的对象本身的属性。
实验4:
实验4与实验3的区别在于,实验4在changeName()中改变了形参user引用的指向,使其指向一个新的User对象。回到main()中打印出来的user仍然是原来的user,这说明实参引用仍然指向原来的user对象。
经过上面分析,先不讨论是值传递还是引用传递,我们基本可以得到结论:
在Java中,经过参数传递和方法调用后,引用内部持有的对象地址不变,即不会改变参数引用指向的对象。
因此结果很明显了,Java中肯定不是引用传递,否则在方法内改变形参引用指向时,实参的引用同样应该改变。
参数传递过程中发生了什么?
唯一有疑惑的地方应该是实验3,因为它看起来像是引用传递,那么我们来分析一下:
首先我们new出一个User,然后将一个user引用指向了这个对象,那么这个引用持有了User对象的内存地址。当调用changeName(User user)方法时,实参user将这个内存地址传递给形参user,所以形参同样也指向了同一个User对象。那么当方法内部改变User对象内属性时,所以我们打印可以看到同时指向User的形参和实参都发生了改变,这其实是对象内的的改变,与参数无关。
而实验2和实验4实际上是一样的实验,实验2看起来比较特殊的原因是name的字符串改变时,形参通过赋值已经指向了另一个String对象。
所以这时结论已经清晰了:Java中的参数传递是值传递。
总结:
按上面的分析我们已经知道了Java是按值传递(call by value)的,那么如何按值传递的呢?根据规律可以发现:
1.当实参为基本数据类型时,传递的是一份字面量值的拷贝。
2.当实参为引用数据类型时,传递的是对象的地址。
网友评论