java中的赋值、引用和参数传递
开门见山,先看代码:
/*
* 1. 定义一个User类型的变量u, 存放在栈中
* 2. new : 创建对象, 存放在堆中
* 3. User() 调用User的构造方法
* 4. = 将对象的地址赋给u, 一同存入栈中
*
*/
User u = new User();
/* 定义一个整型变量 a
将12赋值给a, 一起存在堆栈中
*/
int a = 12;
实例化对象会产生引用变量(值为对应对象的地址,存放在栈
中)和对象自身(存放在堆
中)。
User u0 = new User();
u0.name = "小黄";
//将 u0变量存储的值给u1
User u1 = u0;
u1.name = "大黄";
System.out.println(u0.name);//大黄
会发现,改变u1的值为什么会改变u0的值呢?再看原生数据类型:
public class Main {
public void changeNumber(int arg) {
arg = 12;
}
public static void main(String[] args) {
Main m = new Main();
int number = 0;
m.changeNumber(number);
System.out.println(number);//0
}
}
结果发现number并没有改变???
对于引用数据类型Object
,变量中实际储存的是对象所在的地址,赋值给另一个变量,实际上就是把地址复制一份给新变量。修改对象的属性值,实际上是通过地址找到对象去修改,因为是同一个地址,也就是指向同一对象,对象值修改后,所有引用所访问的值也相应修改。
对于原生数据类型Primitive
,变量和该变量的值一同存在栈中。上面number的数值没有改变,是因为:
public void changeNumber(int arg) {
// arg = number ;传进来的参数赋值给形参,自身并没有发生变化
arg = 12;
}
也就是完成赋值,变量间就彼此独立,互相不受影响。
实际上,无论是原生数据类型还是引用数据类型,参数传递时传的都是值,原生传的就是变量值,引用传的就是地址。再看一个传递引用的例子:
//不改变引用
public void changeObject1(User arg) {
arg.name = "changedName";
}
//改变引用
public void changeObject2(User arg){
arg =new User();
}
public static void main(String[] args){
Main m = new Main();
User u1 = new User();
u1.name = "before";
m.changeObject1(u1);
System.out.println(u1.name);//changedName
m.changeObject2(u1);
System.out.println(u1.name);//changedName
}
changeObject2
之所以没变是因为:
public void changeObject2(User arg){
//arg = u1;把u1指向对象的地址赋给arg
arg =new User();//arg 指向了新的对象
}
arg改变了引用,指向了新的对象,u1自然不受影响。
好了,开始喝橙汁。