package com.jvmfinalstatic;
//需求分析:本节学习java中参数传递过程:
//参考文献:http://blog.sina.com.cn/s/blog_59ca2c2a0100qhjx.html
//参考文献2:http://blog.csdn.net/yangyuankp/article/details/7651251
/*
* 1.基本类型作为参数传递时:
* 基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。
* 2.对象作为参数传递时:
* 当对象作为参数传递时,传递的是对象的引用,也就是对象的地址
* 3.总结:
* 无论是基本类型作为参数传递,还是对象作为参数传递,实际上传递的都是值,只是值的的形式不用而已。
* 第一个示例show1()用基本类型作为参数传递时,将栈内存中的值9传递到了change1方法中。第二个示例
* 中用对象作为参数传递时,将栈内存中的值(指向堆内存中对象的地址)传递到了change2方法中。当用对象
* 作为参数传递时,真正的值是放在堆内存中的,传递的是栈内存中的值,而栈内存中存放的是堆内存的地址,
* 所以传递的就是堆内存的地址。这就是它们的区别。
* */
class Student{
private String name;
private int age;
Student(String name,int age){
this.setName(name);
this.setAge(age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
class BaseParaDeli{
private int data = 9;
//int 是基本类型因此执行这句话就会 在栈内存中直接开辟一个内存把9存入;这个内存的"名字"为data;
public String str = "i am eternal";
// 此时,会在常量池种开辟一个内存,在其中存入"i am eternal";并且在栈内存中开辟一个内存"名字"为
//str其中存放的是常量池中"i am eternal"的地址;
public void show1(){
BaseParaDeli bpd = new BaseParaDeli();
bpd.change1(data);
System.out.println("data = "+data);//输出:结果 data = 9;
/* 原因分析: 调用BaseParaDeli对象的change1方法,并且以date为参数。JVM读到这段代码时,检测到
* change1方法中的 x 是局部变量,第一步:在栈中开辟一块空间把x放入其中,并且把date的值赋给x,
* 此时 栈中这个内存的"名字"为x 其中存放的值为 9;第二步:读到x = 100时,把100赋给x;因此,在
* 栈中就会出现两个内存地址 一个名为 data 存放的是9,两一个名为x存放的是100。第三步:change1方
* 法执行完毕,立即释放局部变量 x 所占用的栈空间
*
* */
}
public void show2(){
BaseParaDeli bpd = new BaseParaDeli();
Student stuOne = new Student("John",25);
bpd.change2(stuOne);
System.out.println(stuOne.getName()+" "+stuOne.getAge());//输出: John 25
/* 原因分析:
* 调用bpd对象的change2方法,以引用stuOne为参数。第一步:JVM检测到change2方法中的stu参数为局部变量,
* 立即加入到栈中,由于是引用类型的变量,所以stu中保存的是stuOne中的指针,此时stu和sutOne指
* 向同一个堆中的对象。在stu和stuOne之间传递是指针(引用/ 地址)。 也就是说,在栈内存中有两个地址:一个
* "名字"为stuOne其中存放的是执行堆中对象的地址(比如XXF100);另一个"名字为"stu的内存里面存放的是同一个地址(XXF100)
* 第二步:当读到:stu = new Student("xiaoMing",100);change2方法中又实例化了一个Student对象,并且赋给stu;
* 即:在堆区new了一个对象,并且把该对象的指针保存在栈中的stu对应空间,此时实例stu不再指向实例stuOne所指向的对象,
* 但是实例stuOne所指向的对象并无变化,这样无法对stuOne造成任何影响,因此输出结果为:John 25;
* 第三步:方法执行完毕后,栈中的内存自动释放,堆中的对象等待回收机制回收;
*
* */
}
public void show3(){
BaseParaDeli bpd = new BaseParaDeli();
Student stuOne = new Student("Mike",30);
bpd.change3(stuOne);
System.out.println(stuOne.getName()+" "+stuOne.getAge());//输出: Mike 200
/*原因分析:
* 调用bpd对象的change3方法,以引用stuOne为参数。第一步:JVM检测到change3方法中的stu参数为
* 局部变量,立即加入到栈中,由于是引用类型的变量,所以stu中保存的是stuOne中的指针,此时stu和
* sutOne指向同一个堆中的对象。在stu和stuOne之间传递是指针(引用/ 地址)。 也就是说,在栈内存中
* 有两个地址:一个"名字"为stuOne其中存放的是执行堆中对象的地址(比如XXF100);另一个"名字为"stu的
* 内存里面存放的是同一个地址(XXF100)
* 第二步:stu.setAge(200);其实就是调用stuOne指向的对象的setDay方法,因为两者指向的是同一堆中的对象
* 所以stu对属性的改变会影响到stuOne的属性。
* 第三步:change3方法执行完毕,立即释放局部引用变量stu
*/
}
public void show4(){
BaseParaDeli bpd = new BaseParaDeli();
bpd.change4(str);
System.out.println("str: "+str);//输出结果:str: i am eternal
/*原因分析:
* 调用bpd对象的change4方法,以字符串str为参数。第一步:JVM检测到change4方法中的s参数为
* 局部变量,立即加入到栈中,由于是字符串类型的变量,所以s中保存的是str中的指针,此时s和
* str指向常量池中同一个对象。
* 第二步:s = s + "is change ?";其实就是在常量池中再开辟一个内存把s= i am eternal is change ?
* 存入其中,并且将栈中s中存放的地址指向它;这样 在栈中有两个内存 s 和 str 堆中也有两个内存,各自
* 指向各自的,因此str的值不会发生改变;
* 第三步:change4方法执行完毕,立即释放局部引用变量s
*
* 总:String变量和基本数据类型包装类中的那六个是一样的道理:可以参考上篇文章;
*
*
* */
}
public void change1(int x){
x = 100;
}
public void change2(Student stu){
stu = new Student("xiaoMing",100);
}
public void change3(Student stu){
stu.setAge(200);
}
public void change4(String s){
s = s + "is change ?";
}
}
public class ParameterDelivery {
public static void main(String[] args) {
BaseParaDeli bp = new BaseParaDeli();
bp.show1();
bp.show2();
bp.show3();
bp.show4();
}
}
java:参数传递过程初学
最新推荐文章于 2022-01-01 17:55:46 发布