Java——值传递和引用传递
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Java——值传递和引⽤传递
值传递
在⽅法被调⽤时,实参通过形参把它的内容副本传⼊⽅法内部,此时形参接收到的内容是实参值的⼀个拷贝,因此在⽅法内对形参的任何操作,都仅仅是对这个副本的操作,不影响原始值的内容。
先来看个例⼦:
public static void valueCross(int age,float weight) {
System.out.println("传⼊的age值:"+age);
System.out.println("传⼊的weight值:"+weight);
age=23;
weight=60;
System.out.println("修改后的age值:"+age);
System.out.println("修改后的weight值:"+weight);
}
public static void main(String[] args) {
int age=10;
int weight=50;
valueCross(age,weight);
System.out.println("⽅法执⾏后的age:"+age);
System.out.println("⽅法执⾏后的weight:"+weight);
}
运⾏结果:
传⼊的age值:10
传⼊的weight值:50.0
修改后的age值:23
修改后的weight值:60.0
⽅法执⾏后的age:10
⽅法执⾏后的weight:50
我们可以看到valueCross⽅法执⾏后,实参age和weight的值并没有发⽣变化,这是什么原因?
⾸先程序运⾏时,先从main⽅法开始执⾏,此时JVM为main()⽅法往虚拟机栈中压⼊⼀个栈帧,即为当前栈帧,⽤来存放main()中的局部变量表(包括参数)、操作栈、⽅法出⼝等信息,如a和w都是mian()⽅法中的局部变量,因此可以断定,age和weight是躺着mian⽅法所在的栈帧中
接着调⽤valueCross⽅法,此时JVM为valueCross()⽅法往虚拟机中压⼊⼀个栈帧,即为当前栈帧,⽤于存放valueCross⽅法的局部变量等信息;因此age和weight是躺着valueCrossTest⽅法所在的栈帧中,⽽他们的值是从a和w的值copy了⼀份副本⽽得,如图:
因此这两个age和weight对应的内容不是同⼀个,在valueCross⽅法中修改的只是⾃⼰栈中的内容,并没有修改main⽅法栈中的内容
引⽤传递
”引⽤”也就是指向真实内容的地址值,在⽅法调⽤时,实参的地址通过⽅法调⽤被传递给相应的形参,在⽅法体内,形参和实参指向同⼀块内存地址,对形参的操作会影响的真实内容。
先有⼀个Person类代码如下:
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
= name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
测试类代码:
public class TestArr {
public static void PersonCross(Person person) {
System.out.println("传⼊的person的name:"+person.getName());
person.setName("敖丙");
System.out.println("⽅法内重新赋值后的name:"+person.getName());
}
public static void main(String[] args) {
Person p=new Person();
p.setName("哪吒");
p.setAge(4);
PersonCross(p);
System.out.println("⽅法执⾏后的name:"+p.getName());
}
}
测试结果1:
传⼊的person的name:哪吒
⽅法内重新赋值后的name:敖丙
⽅法执⾏后的name:敖丙
我们可以看到PersonCross⽅法执⾏后,person的name值被改变了
下⾯再看⼀段代码:
public class TestArr {
public static void PersonCross(Person person) {
System.out.println("传⼊的person的name:"+person.getName());
person=new Person();//新添加的代码
person.setName("敖丙");
System.out.println("⽅法内重新赋值后的name:"+person.getName());
}
public static void main(String[] args) {
Person p=new Person();
p.setName("哪吒");
p.setAge(4);
PersonCross(p);
System.out.println("⽅法执⾏后的name:"+p.getName());
}
}
测试结果2:
传⼊的person的name:哪吒
⽅法内重新赋值后的name:敖丙
⽅法执⾏后的name:哪吒
有没有发现什么不同,这次PersonCross⽅法执⾏后person的name值并没有改变,这⼜是为什么?
我们知道,java中的对象和数组是存放在堆内存中的,⽽堆内存是线程共享的,所以main⽅法执⾏时,会在堆内存中开辟⼀块内存,⽤来存储p对象的所有内容,然后再栈内存中创建⼀个引⽤p存储堆区中p对象的真实地址,如下图:
当执⾏到PersonCross⽅法时,因为⽅法内有这么⼀⾏代码:person=new Person(),此时JVM在堆内存中⼜开辟了⼀块内存空间,假设地址为xo2222,那么现在的person则指向了xo2222这块内存,现在修改person的name值修改的是xo2222这块内存空间的值,不会改变xo3333的值,所以测试结果2中的name没有发⽣变化
引⽤传递本质上就是值传递,将引⽤变量的值传递给形参,因为引⽤变量的值存放的是地址值,所以当地址值传递给形参后,形参和实参指向同⼀块内存区域。