对于java变量的传递到底是传递值还是传递引用,一般而言,基本类型的变量是值传递;对象类型的变量是引用传递。其实引用传递也是传递的值,别懵,看完就懂!
基本类型
就基本类型int而言,变量a存放的就是字面值3
int a = 3;
int b = a; //将a 的值复制一份,再赋值给b;
a = 5;//重新修改a的值
最终a和b的值为:
a = 5;
b = 3;
b = a,其实就是把a的值拷贝一份,然后再赋值给b;因此a和b并没有什么联系;
a = 5,把a所存的内容由3改为5,b不会有影响。
对象类型
先了解引用里面到底存放的什么,如下。
引用p指向的是new People();的这个对象的地址,也就是引用存放的是对象的地址。
People p = new People();
案例
class People {
int age = 0;
}
public class Test{
public static void main(String args[]){
People p1 = new People();
People p2 = new People();
p1 = p2;
p2.age = 20;
System.out.println(p1.age);
System.out.println(p2.age);
}
}
输出结果
20
20
结果发现p1.age和p2.age一样都为20;这是因为p2向p1赋值的时候p1 = p2;
p2将自己的引用所指向的地址拷贝给了p1,因此p1和p2这个时候都指向了同样的地址;如下图:
本来p1和p2分别指向不同的地址:
随后p1 = p2;,p2将自己的指向的地址拷贝一份,然后赋值给p1,那么p1指向了和p2一样的地址:
p2.age = 20;最后将该地址下的age属性值该为20,那么p1.age和p2.age都变为20.
从上面的例子我们就可以知道对象传递的是引用,那么为什么说java的参数传递都是指传递呢?其实我们可以这样想,引用传递就是传递引用指向地址的值,那么也是传递的值,只是基本类型传递的值是字面量的拷贝,其他类型传递的是引用地址的值的拷贝。
案例分析
案例1
public class TestTransferValue {
public void changevalue1(int a){
a= 30;
}
public static void main(String[] args){
TestTransferValue test = new TestTransfervalue();
int age = 20;
test.changevalue1(age);
System.out.println(" age----" +age);
}
}
输出结果
age----20
age首先被初始化为20,然后调用方法changevalue1(age),age变量会将自己的一个副部传递这个这个方法,那么参数a = age,然后a = 30结束,最终只是改变了a 这个参数(或者说是改变了age的一个副本),与age变量无关。
案例2
public class TestTransferValue
{
public void changevalue2 (Person person){
person.setPersonName(" xxx" ) ;
}
public static void main(String[] args){
TestTransferValue test = new TestTransfervalue();
Person person = new Person(personName: "abc");
test.changevalue2(person);
System.out.println("personName-----"+person.getPersonName());
}
}
打印结果:
personName-----xxx
创建一个对象person ,其属性初始化为abc,然后调用changevalue2(person)修改了personName属性;为什么这次修改就会成功呢?首先,对于这个方法,person传递的是引用所指向的地址,那么该方法的参数指向的地址与person一样,他们所指向的是同一个地址,该方法将该地址的内容改变了,那么person的属性就发生了变化。
案例3
public class TestTransferValue{
public void changeValue3(String str){
str = "xxx" ;
}
public static void main(String[] args){
TestTransferValue test = new TestTransfervalue();
String str = "abc";
test . changevalue3(str);
System. out . println("string-----"+str);
}
}
打印结果:
string-----abc
有没有觉得很意外?如果没有,那么恭喜你已经明白了。
String是复杂类型的,那么它传递的也是引用。但是注意,当我们把str的引用(指向的地址)拷贝给了changeValue3(String str)方法的参数,那么他们都指向了同一个地址,这里没毛病;重要的下面,str = “xxx” ;方法的参数重新了赋值,那么该参数str就重新指向了一个新的地址("abc"的地址),因此他们所指向的地址不同了,而对象str的地址和内容都没有发生变化。