Java中值传递 引用传递
一直以来对按值传递,引用传递,以及堆栈上的对象不是很明白,今天整理一下自己的想法
- 形参:用于定义方法的时候使用的参数
- 说明:只有在被调用时才会分配内存单元,在调用结束,即刻释放所分配的内存单元。因此,只在方法内才有效。
- 实参:用于调用时传递给方法的参数
- 按值传递:实际参数把它的值传递给对应的形式参数,函数接收的是原始值的一个copy
- 引用传递:方法调用时,实际参数的引用(地址,而不是参数的值)被传递给方法中相对应的形式参数,函数接收的是原始值的内存地址
先上一段代码,看下运行结果
public class ReferencePkValue2 {
public static void main(String[] args) {
ReferencePkValue2 t = new ReferencePkValue2();
int a=99;
t.test1(a);
System.out.println(a);
MyObj obj=new MyObj();
t.test2(obj);
System.out.println(obj.b);
t.test3(obj);
System.out.println(obj.b);
}
public void test1(int a){
a++;
System.out.println(a);}
public void test2(MyObj obj){
obj = new MyObj();
obj.b=100;
System.out.println(obj.b);}
public void test3(MyObj obj){
obj.b=100;
System.out.println(obj.b);
}
}
class MyObj{public int b=99;}
打印结果
100
99
100
99
100
100
1在栈中创建一个变量为a的引用,然后查找有没有字面值为99的地址,没找到,就开辟一个存放99这个字面值的地址,然后将a指向99的地址,如果有则直接指向该地址。在调用test1时,在实参a传入,由形参a接收,可以理解为copy了一份,此时存在了两个变量,形参a++,但是实参a并未改变,所以输出结果为100 99
2在堆中开辟一块内存用来生成对象MyObj,同时创建了一个引用obj,里面存在MyObj的地址。在调用test2时,实参obj传入,形参obj接收,同样理解为copy了一份,然后执行obj=new MyObj(),在堆上重新开辟了一块内存B,同时将copy的obj指向该内存,此时obj.b=100,数据改变的是内存B,方法执行结束,copy的obj销毁,所以输出结果为100 99
3在2的基础上,因为copy的obj的值和实参的值是完全一样的,所以它俩都指向堆上的MyObj,所以执行了obj.b=100之后,MyObj中的东西发生了变化,方法结束,copy的obj销毁,但是MyObj的内容已经改变所以输出结果为100 100
总结:Java中都是按值传递,不管是基本类型还是引用类型,形参都是实参的一个拷贝。对形参的修改不会影响到实参。形参只是实参的一个拷贝,是两个不同的东西。但是因为形参和实参的值相同,都指向同一个对象,所以对形参所指向的对象的修改会影响到实参所指向的对象。。