问题场景
在项目中有这样一段伪代码:
A方法调用B方法,传入引用类型的入参C。
B方法在业务处理后将新的引用指向入参。
在A方法调用完B方法后,会继续操作入参C。
A方法如下
void A(){
.....业务处理
//C是一个对象
C c = ...
//调用B方法
void B(c)
.....业务处理,继续操作参数c
}
B方法如下
void B(入参){
.....业务处理
入参 = 新的引用
.....业务处理
}
本来以为B方法对参数引用进行修改后,A方法可以获取到修改后的入参C,但是在实际业务处理的过程中发现,入参C还是以前的引用。
问题分析
方法的每一个参数,不管是局部变量还是方法入参,在方法栈帧的局部变量表里,都会占用相应的slot。
B方法被调用时,在B方法的局部变量表的slot也会存放入参数的引用,假设为D,这个引用和入参C的引用,指向同一个对象。
如下图所示
假如我们在B方法修改了D的引用,让其指向了一个新的对象,那么上述变化如下所示
可以发现,对于入参C来说,指向的对象内容并未改变。
而如果我们在B方法中仅仅是修改了对象内容,比如修改了age属性,而不是指向新的引用,如下
那么此时A方法操作的入参C,已经发生了改变。