在讲解对象引用传递之前,给大家两个简单的例子:
例子1:
public class Student{
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void changeStudentName(Student s) {
s = new Student();
s.setName("nihao");
}
public static void main(String[] args) {
1 Student student = new Student();
2 student.setName("珠宝呀");
3 *System.out.println(student.getName());*
4 student.changeStudentName(student);
5 *System.out.println(student.getName());*
}
}
output:
珠宝呀
珠宝呀
你会发现,即便我调用了changeStudentName方法,其输出结果也是一样的,为什么会这样呢?我们来画一个类加载的JVM结构图,当我们执行语句1时,首先会在栈里分配一个地址空间存储指向student对象1的引用的首地址。
当我们执行语句2的时候,在栈里面分配一个临时变量name,临时变量存储是常量池当中的“珠宝”的地址,而通过set方法中的this.name=name,此时对象的属性存储的临时变量的副本地址,通过这个方法可得:
String p="珠宝呀";
student.setName(p);
student.setName("珠宝");
System.out.println("student-->"+student.getName());
System.out.println("p-->"+p);
output:
student-->珠宝
p-->珠宝呀
发现p的值并不没改变,而对象name重新获取新的副本。这个是按值传递。
当方法执行4时:此时获取了student对象的副本,副本指向了新的Student对象,并且set了新的名字,而Student初值并没有改变,因而,输出的结果是没有改变。
如果长StudentName的返回对象改变了,就会出现不同的结果:
public Student changeStudentName(Student s) {
s = new Student();
s.setName("nihao");
return s;
}
public static void main(String[] args) {
Student student = new Student();
System.out.println(student.getName());
String p="珠宝呀";
student.setName(p);
student.setName("珠宝");
System.out.println("student-->"+student.getName());
System.out.println("p-->"+p);
student = student.changeStudentName(student);
System.out.println("student-->"+student.getName());
}
output:
student-->珠宝
p-->珠宝呀
student-->nihao
因为,通过调用 student.changeStudentName(student);这个方法,返回的是一个新的对象的引用,而student重新指向了新的引用对象,故而,值就被改变了。这个是按引用传递数据。