参数传递图解与结论
通过上面的两段程序可以得出如下结论:根据内存去解释,局部变量随方法栈的弹出而消失;
当调用方法时,如果传入的数值为基本数据类型(包含String类型),形式参数的改变对实际参数不影响
当调用方法时,如果传入的数值为引用数据类型(String类型除外),形式参数的改变对实际参数有影响
因为局部变量随方法栈的弹出而消失,所以当调用方法时,如果传入的数值为基本数据类型(包含String类型)时,局部变量的改变对实际参数无
影响,如果传入的数值为引用数据类型(String类型除外),此时程序未结束,对象在堆中还存在,所以形式参数的改变对实际参数有影响。
对象的内存图解
基本类型和引用类型作为参数传递
基本类型作为参数传递时,其实就是将基本类型变量x空间中的值复制了一份传递给调用的方法show(),当在show()方法中x接受到了复制的值,再在show()方法中对x变量进行操作,这时只会影响到show中的x。当show方法执行完成,弹栈后,程序又回到main方法执行,main方法中的x值还是原来的值。
当引用变量作为参数传递时,这时其实是将引用变量空间中的内存地址(引用)复制了一份传递给了show方法的d引用变量。这时会有两个引用同时指向堆中的同一个对象。当执行show方法中的d.x=6时,会根据d所持有的引用找到堆中的对象,并将其x属性的值改为6.show方法弹栈。
由于是两个引用指向同一个对象,不管是哪一个引用改变了引用的所指向的对象的中的值,其他引用再次使用都是改变后的值。
3.4.2对象的内存解释
class Person {
private int age;
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
}
public class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
p.setAge(30);
System.out.println("大家好,今年我" + p.getAge() + "岁");
}
}
程序执行流程说明:
1、先执行main方法(压栈),执行其中的 Person p = new Person();
2、在堆内存中开辟空间,并为其分配内存地址0x1234,紧接着成员变量默认初始化(age = 0);将内存地址0x1234赋值给栈内存中的Person p 变量
3、继续执行p.setAge(30)语句,这时会调用setAge(int age)方法,将30赋值为setAge方法中的“age”变量;执行this.age = age语句,将age变量值30 赋值给成员变量this.age为30;
4、setAge()方法执行完毕后(弹栈),回到main()方法,执行输出语句System.out.println(),控制台打印p对象中的age年龄值。
注意:
this到底代表什么呢?this代表的是对象,具体代表哪个对象呢?哪个对象调用了this所在的方法,this就代表哪个对象。
上述代码中的 p.setAge(30)语句中,setAge(int age)方法中的this代表的就是p对象。