结论:Java中只有值传递
很多人困惑既然是值传递,为什么有的时候还能改变原对象属性呢?
值传递和引用传递区别:值传递会创建副本作为参数,而引用传递是直接作为参数
验证结论:
基本类型时
public class Demo01 {
@Test
public void test(){
int i=1;
add(i);
System.out.println(i);
}
public void add(int i){
i+=1;
System.out.println(i);
}
}
输出
2 1
可见,将基本类型变量作为参数传递到方法中,在方法中对其进行修改,是不会影响变量自身的值
引用类型时
public class Demo01 {
@Test
public void test(){
Student student = new Student();
student.name="aa";
updateName(student);
System.out.println(student.name);
}
public void updateName(Student student){
student.name="bb";
System.out.println(student.name);
}
}
class Student{
String name;
}
输出
bb bb
上述代码。编写了一个Student类,然后创建了一个对象,设置name属性为aa,然后调用updateName方法对象name属性进行修改,最终发现值传递情况下原对象属性也被修改了。
这是为什么?因为参数类型为引用类型时,传递的时引用地址的副本,因此在方法中也可以使用这个副本操作该对象的属性,因为这个副本指向的地址和该对象是一样的
既然值传递也能改变对象属性,那么二者怎么区分呢,再看一个例子
public class Demo01 {
@Test
public void test(){
Student student = new Student();
student.name="aa";
updateName(student);
System.out.println(student.name);
}
public void updateName(Student student){
student=new Student();
student.name="bb";
System.out.println(student.name);
}
}
class Student{
String name;
}
输出
bb aa
这次在方法中没有直接修改对象的属性,而是创建了一个新对象,然后将其引用复制给该变量,然后修改属性,此时原对象的属性是没有被修改的。
这也验证了值传递,传递的是引用地址的副本,因此方法中只是改变了引用副本,让其指向其他对象,但是原引用是没有被改变的,还是指向原对象,因此也就不能修改原对象的属性了。
拓展
public class Demo01 {
@Test
public void test() {
String str = "aa";
updateStr(str);
System.out.println(str);
}
public void updateStr(String str) {
str = "bb";
System.out.println(str);
}
}
输出
bb aa
道理和上面的一样,str = "bb";相当于让引用副本指向的其他对象,原引用还是指向"aa"这个对象。
最终结论:Java中只有值传递,若参数为基本类型,则传递的就是基本类型变量值的副本;若为引用类型,则传递的是引用地址的副本,该引用副本也能修改对象,因为虽然是副本,但是和原引用都是指向一个对象。但是让引用副本指向其他对象,这不影响原引用,原引用还是指向原对象,这种情况下修改就不会对原对象产生影响。