方法中参数传递的机制
参数的传递都是「值传递」,在调用方法的时候,参数会被创造出一个副本,原本的值是不会改变的。基本数据类型,也称为「值类型」。
- 基本数据类型(值类型)的值传递
package ketangzuoye;
public class Ceshi1 {
//构造一个两个参数的方法用于计算两个值都加5
void fun1(int a, int b) {
a = a + 5;
b = b + 5;
System.out.println("调用方法时a的值:" + a);
System.out.println("调用方法时b的值:" + b);
}
public static void main(String[] args) {
Ceshi1 ceshi = new Ceshi1();
int a = 10;
int b = 20;
System.out.println("调用方法前a的值:" + a);
System.out.println("调用方法前b的值:" + b);
ceshi.fun1(a,b);
System.out.println("调用方法后a的值:" + a);
System.out.println("调用方法后b的值:" + b);
}
}
控制台打印结果:
调用方法前 a 的值:10
调用方法前 b 的值:20调用方法时 a 的值:15
调用方法时 b 的值:25调用方法后 a 的值:10
调用方法后 b 的值:20调用方法前和调用方法后a和b的值都没有发生变化,但调用方法时a和b的值发生的变化,验证了参数的传递在调用方法的时候,参数会被创造出一个副本,原本的值是不会改变的。
通过内存解析图解释参数在方法中的传递过程
第一步
程序主方法 main()在执行时从上而下首先执行变量声明的两行代码,
int a = 10;
int b = 20;
内存空间发生的变化如图所示:
- 首先,在栈内存开辟两个空间分别存放 a 和 b,地址(hashcode)为 null。
- 然后,在常量池存放字面量 10 和 20,并分别生成它们的特有地址 3308 和 3309(这里的地址是随便写的,仅用于举例,真是地址并非如此)。
- 最后,分别将字面量 10 的地址 3308 和字面量 20 的地址 3309 分别赋给 a 和 b,最终在栈区形成 a 以及 a 对应的地址为 3308 和 b 以及 b 对应的地址 3309。
第二步
执行控制台打印输出语句
System.out.println("调用方法前a的值:" + a);
System.out.println("调用方法前b的值:" + b);
打印结果:调用方法前 a 的值:10,调用方法前 b 的值:20。
第三步
执行方法fun1(),执行控制台打印输出语句
ceshi.fun1(a,b);
System.out.println("调用方法时a的值:" + a);
System.out.println("调用方法时b的值:" + b);
打印结果:调用方法时 a 的值:15,调用方法时 b 的值:25。
内存空间发生的变化如图所示:
- 首先,调用方法时,生成参数a、b的副本a’、b’同时在栈内存开辟空间存放a’、b’,并将a、b的值地址传递给a’、b’。
- 然后,执行方法体语句 a’ = a’ + 5 和 b’ = b’ + 5即 a’ = 10 + 5 = 15 和 b’ = 20 + 5 = 25,并将新生成的字面量 15 和 25 存放在常量池,同时生成对应地址 3311 和 3312。
- 最后,再将新的地址 3311 和 3312 分别赋给 a’ 和 b’,在栈区形成 a’ 以及 a’ 对应的地址为 3311 和 b’ 以及 b’ 对应的地址 3312。
第四步
执行控制台打印输出语句
System.out.println("调用方法后a的值:" + a);
System.out.println("调用方法后b的值:" + b);
打印结果:调用方法后 a 的值:10,调用方法后 b 的值:20。