当前位置: 首页 > 科技观察

面试官:为什么Java只传值?

时间:2023-03-20 01:12:03 科技观察

面试官爱问的一个基本问题:Java是按值传递还是按引用传递?对于这个问题想必每个人都有自己的看法,那么真相究竟如何,又该如何回答面试官的问题呢?今天来分析一波价值转移?通过引用?首先,我们要知道什么是值传递,什么是引用传递。只有知道了这一点,我们才能理解Java是如何做到的。要想理解这两种传递,就需要理解形参和实参这两个概念。形参:定义函数时使用的参数,用来接收函数传入的参数,比如我们写一个函数,函数中的参数就是形参publicvoidtest(Stringstr){//str就是形参System.out。println(str);}实参:当我们调用函数时,函数名后括号内的参数称为实参,如下例所示publicstaticvoidmain(String[]args){Aa=newA();a.test("chengxukong");//chengxukong为实参}可以发现,调用带参数的函数时,会将实参传递给形参;所以这个传递过程有两种情况,即值传递和引用传递。值传递就是把参数的值给你。调用函数时,复制实参传递给函数,这样函数内部参数的修改不会影响实参;和引用传递不同,它直接把参数的实际地址给了调用函数,地址的内容可以在函数内部直接修改,会影响实际参数我举个例子,我们公司有一个数据库A,只允许内部人员操作。现在有一个项目需要和其他公司合作。这个数据库的数据需要交给合作公司。我总不能直接把我们数据库A的地址给他们,让他们直接连接我们的数据库A吧,要是他们删了数据库跑了,那我老大就不会杀我拜天了。所以这个时候,把我们数据库表的数据复制到一个新的数据库B中,合作公司就可以查看到这个数据库B的数据,他们也可以随意操作,不会影响我们的数据库。这个操作类似于按值传递。如果合作公司直接操作我们的数据库,类似于引用传递。现在大家应该知道Java按值传递和按引用传递的区别了吧。?我们理解值传递和引用传递的概念,那么在Java中它是一种什么样的传递方式呢?下面看代码分析publicstaticvoidmain(String[]args){Fansfans=newFans();intt=1;fans.test(t);System.out.println("Inmain:"+t);}publicvoidtest(intt){t=2;System.out.println("Intest:"+t);}//输出Intest:2Inmain:1上面代码,main中定义的t的值为1,在函数test中参数t的值修改为2,这个结果容易分析吗?test函数并没有改变传入的t的值,根据我们上面的介绍,是不是可以得出一个结论:Java是按值传递的?有人可能会质疑你传入的参数t是一个基本类型。如果你通过Enter引用对象类型,那么它肯定会改变对象内容,OK,我们来看一个引用类型代码inta=10;Stringb="fans";publicvoidtest(Fansfans){fans.a=20;fans.b="newFans";System.out.println("Intest,A:"+fans.a+",B:"+fans.b);}publicstaticvoidmain(String[]args){Fansfa=newFans();fa.test(fa);System.out.println("Inmain,A:"+fans.getA()+",B:"+fans.getB());}//输出Intest,A:20,B:newFansInmain,A:20,B:newFans哦,输出是一样的,就是传入的fans对象被函数test修改了,那么这个是不是又变成了pass-by-reference呢?所以得出基本类型是值传递,引用类型是引用传递?这是事实吗?让我们试试publicvoidtest(Stringt){t="BBB";System.out.println("Intest:"+t);}publicstaticvoidmain(String[]args){Fansfans=newFans();Stringtt="AAA";fans.test(tt);System.out.println("Inmain:"+t);}//OutputIntest:BBBInmain:AAA,好肥的东西,传上来的参数的值都没有修改,那怎么能它再次被更改为一个值?通过以上三个例子后,性能结果是不一样的。结论是什么?我们一起来分析一下,第一个输入是基本类型。基本类型指向值。转移类似于赋值操作,不会影响原值。它类似于a=10,b=a,b=20不会把a变成20;第二个引用对象传入引用类型fans的地址值,而原参数fa指向地址0x123456,所以函数test的参数fans也指向0x123456。该函数在内部修改引用风扇,因此修改了地址0x123456的值,从而导致外部更改。第三个引用对象是String类型,而原来的参数tt指向地址0x123456,而函数test的参数t也指向0x123456的值,那么为什么这和第二个结果不一样呢?重点是t="BBB";这句话本来是想尝试把内容“AAA”改成“BBB”,无奈,String类型是staticfinal类型,这个大家应该都知道,不知道的就去补为了它。看了String的源码,所以变成了t=newString("BBB"),t指向另一个地址,这个地址的内容是"BBB",所以原来的引用tt还是指向原来的地址0x123456,不是改可能有同学会问,为什么这个地址的内容在第二个可以改,第三个不能改?很明显,String是final的,不能修改,第二个可以直接修改地址的内容;那么问题又来了,这样的话,还能叫价值转移吗?告诉你,是传值,因为我们第二种验证方式是错误的,如果你加上fans=newFans();到函数的第一行,你可以看到它还输出了什么,它变得和第三个AString类似。如果改变函数参数的指向位置,函数外和函数内的输出会不同,函数内不会影响外;如果按引用传递,即使加上这句话,也应该是函数内外的输出是一样的。而且,这也违背了引用传递的概念,会改变传入的参数。想过按值传递和按引用传递,并不是根据传递的内容来区分的。通过的不一定是引用。引用传递根据定义结果区分;在Java中,使用按值传递(记住,下次面试不要弄错)。在其他方法中,更改引用类型的值是通过引用更改的。当传递引用对象时,对象句柄被复制,即在内存中复制一个句柄,两个句柄指向同一个对象,所以如果改变句柄对应空间的数据,它会影响外部变量