java传值还是传引用,我得说两句

我们为啥要讨论java传值还是传引用?因为不同的传递方式,导致的结果不一样

change(int s){s=100;}

void test(){

      int i=10;

      change(i);//i的值不会变

}

change2(Student student){

       student.setScore(100);

}

void test2(){       

       Student stu=new Student();

       stu.setScore(90);

       change2(stu);//stu的score变成100

}

上面的结果大家想必都知道了,但是为啥?什么叫传值,什么叫传引用,还有些地方说java只会有传值,到底是什么意思,其实不用过于纠结,知道原理就好办了...

jvm中,每个线程对应一个栈结构,这个线程执行过程中,每调用一个方法,就会往这个栈中压入一个栈桢,方法里的参数、局部变量都存在栈桢里,一个叫局部变量表的地方

如果变量是基本类型的,比如int i=10;那在局部变量表中存的就是10这个

如果变量是非基本类型的,比如Student stu=new Student();那在局部变量表中存的就是stu这个变量值,那stu的值是啥呢?就是一串地址,比如0x0001,这个地址指向了new Student()这个对象在堆中的起始地址(在java中,如果一个变量中存储的数值代表的是另外一块内存的起始地址,就称这个变量为引用,stu是new Student()对象的引用)

那么,重点来了,在方法调用时,我们传的到底是啥?其实就是局部变量表里存的东西,如果是基本类型,那就是它对应的值10,如果是非基本变量,那就是一串地址0x0001(上面说了,地址代表引用)。所以说基本类型传值,非基本类型传引用,原因就在于此

那传过去后,发生了什么呢,我再把上面的代码贴过来

change(int s){s=100;}

void test(){

      int i=10;

      change(i);

}

前面说了,每调用一个方法就往线程栈里压入一个栈桢,桢里面有局部变量表,参数就存在里面

test方法被调用时,压入一个栈桢A,A里面有个局部变量表,存了个10,调用change后,又压入了一个新栈桢B,B中的局部变量表里也存了个10,change方法里将参数重新赋值为100,就将局部变量表里的10替换成了100,当然了,这个局部变量表是B栈桢里的,和A已经没啥关系了,所以i依然是10

change2(Student student){

       student.setScore(100);

}

void test2(){       

       Student stu=new Student();

       stu.setScore(90);

       change2(stu);

}

test2方法被调用时,压入一个栈桢A,A里面有个局部变量表,存了个0x0001,调用change2后,又压入了一个栈桢B,B中的局部变量表里也存了个0x0001,指向了new Student()对象在堆内存中的起始地址,调用setScore(100)操作时,jvm会通过0x0001找到new Student()对象,然后把它里面的socre属性设置为100,由于外面的stu也指向着new Student(),所以score=100,对它也是可见的

我们再改一改

change2(Student student){

       student=new Student();

       student.setScore(100);

}

change2方法新增了一行,student=new Student();其他不变,那对外面的stu还有影响吗?

答案是没有,student=new Student()操作干了这样几件事,在堆中创建一个新的Student对象,拿到它的起始地址,赋值给student变量,并存在change2方法的局部变量表中,对应的变化就是这样

student指向变成了新的Student对象,和stu已经没啥关系了,自然对它没有影响

从上面我们可以看出来,赋值操作的特殊性,赋值操作的作用对象是变量本身,而setScore()这种操作,作用对象是堆中的内容,两者的含义是完全不同的。赋值操作会将变量的值变成新值,不管是基本类型还是引用类型,一旦被重新赋值,那它就不是原来的它了,两者就不再有任何联系了。而变量调用setScore()这种操作,那它还是原来的它,只是内容变了下

所以再看到类似代码时,只要你看到的是赋值操作,甭管它是啥类型,和外面的变量就没啥关系了,方法里咋变都对外面没影响

写到这里我想到网上有一类用String类型当做参数的问题,大意是这样的:

public static void changeString(String s){//改变String型变量的函数

       s="changeString";

}

调用代码:

String str="abc";

changeString(str);

完了之后当然str还是"abc",这是对的,但是好多解释竟然说是因为String是不变类,所以这里怎么修改str还是不会变

好吧,String类确实是final类型的,但这并不应该拿来解释这个现象,进入changeString方法后,做了一个赋值操作,s指向另一个对象"changeString"的地址去了,当然怎么变也不会影响到str了,就这么简单

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值