面试官:Java为什么只有值传递?
面試官愛問的一個基礎問題:Java是值傳遞還是引用傳遞?
想必大家都對這個問題都有自己的看法,那到底事實是怎樣的,我們又該如何回答面試官這個問題呢?今天咱們就來好好分析一波
值傳遞?引用傳遞?
首先,我們得先知道什么叫值傳遞,什么叫引用傳遞,知道這個才能理解Java到底如何做的。若想理解這兩種傳遞需要先理解形式參數和實際參數兩個概念
形式參數:定義函數時使用的參數,用來接收函數傳入參數,比如我們寫個函數,函數中的參數為形式參數
public void test(String str) { //str為形式參數System.out.println(str); }實際參數:我們調用函數時,函數名后面括號中的參數稱為實際參數,如下面例子所示
public static void main(String[] args) {A a = new A();a.test("chengxukong");//chengxukong則為實際參數 }可以發現,當調用一個有參函數的時候,會把實際參數傳遞給形式參數;于是這個傳遞的過程便有兩種情況,即值傳遞和引用傳遞
值傳遞就是把參數的值給你,調用函數時將實際參數復制一份傳遞到函數中,這樣函數內部對參數內部進行修改不會影響到實際參數;而引用傳遞就不一樣了,它直接把參數的實際地址給調用函數了,函數內部可直接修改該地址內容,會影響到實際參數
我來舉個例子,我司有一個數據庫A,僅允許內部人員操作,現在有個項目需要和別的公司合作,該數據庫的數據需要交給合作公司一份,我總不能直接把我司數據庫A地址給他們,讓他們直接連我們數據庫A吧,他們要是刪庫跑路了,那我boss豈不要殺我祭天了
所以這個時候,把我司數據庫表數據拷貝一份到一個新的數據庫B,合作公司可以看這個數據庫B數據,他們也可以隨意操作,不會影響我司數據庫
這個操作就類似于值傳遞,如果合作公司直接操作我司數據庫,就類似于引用傳遞了,這下大家應該曉得兩者之別了
Java值傳遞還是引用傳遞?
我們了解了值傳遞和引用傳遞的概念,那Java中到底是哪種傳遞方式呢?我們來看代碼分析
public static void main(String[] args) {Fans fans = new Fans();int t = 1;fans.test(t);System.out.println("In main:" + t);} public void test(int t) {t = 2;System.out.println("In test:" + t);} //輸出 In test:2 In main:1上述代碼,在main中定義t的值是1,在函數test中修改了參數t的值為2,這個結果是不是很容易分析出來了呢?test函數并未改變傳入的t的值,那按照上面我們的介紹是不是可以得出結論:Java中是值傳遞
有的人可能會質疑,你傳入的參數t是基本類型,你若傳入引用對象類型,那肯定就會改變對象內容了,OK,再來看一段引用類型代碼
哎啊,輸出結果竟然一樣了,也就是傳入的fans對象被函數test修改了,那這樣是不是又變成了引用傳遞了?
于是得出結論,基本類型是值傳遞,引用類型是引用傳遞?事實是這個樣子嗎,我們再來通過String這個引用類型實驗下
啊,這,咋肥事,傳遞的參數值并未修改,怎么又變成值傳遞了
上述三個例子表現結果各有差異,到底結論是什么呢?一起來分析下
第一個傳入的是基本類型,基本類型指向的就是數值,傳遞類似于賦值操作,不會對原數值產生影響,就是類似于a=10,b=a,b=20這種,并不會使a變為20;
第二個引用對象傳入的是引用類型fans的地址的值,傳入的原參數fa指向地址0x123456,所以函數test的參數fans也指向0x123456,函數內部對引用fans進行修改,于是修改了0x123456地址的值,造成外部改變
第三個引用對象是String類型,同樣傳入的是原參數tt的指向地址0x123456,函數test參數t也是指向0x123456的值,那為什么這個和第二個結果不一樣的嘞?重點在于 t="BBB"; 這一句本來想嘗試著使內容"AAA"改變成"BBB",但是無奈,String類型是static final類型的,這個大家應該曉得的不,不曉得的該去補課讀讀String的源碼了,于是變成了 t=new String("BBB"),t指向了另一個地址,這個地址的內容是"BBB",所以原來的引用tt還是指向原來的地址0x123456,并未改變
有的同學可能會提出問題了,為什么第二個可以改變這個地址的內容,第三個不行?很明顯啊,String是final的,不可修改,而第二個可以直接修改該地址的內容;那問題又來了,既然這樣,還能叫值傳遞嗎?
告訴你,就是值傳遞,因為我們第二個的驗證方法不對,你如果在函數的第一行加上個fans = new Fans();你看看它還輸出啥,這就變成和第三個String類似的道理了,改變了函數參數的指向位置,函數外部和函數內部輸出就不一樣了,函數內部也就不會影響外部了;如果按照應引用傳遞,即使加了這一句,也應該是函數內外都是輸出一樣的,況且,這也有悖于引用傳遞的會改變傳入參數的概念
思考
值傳遞和引用傳遞并不是按照傳遞的內容來區分的,傳遞的是引用的并不一定的引用傳遞,根據定義結果來區分;
在Java中用的是值傳遞(記好咯,下次面試別回答錯了)
在其它方法里面改變引用類型的值都是通過引用改變的,當傳遞引用對象的時候,傳遞的是復制的引用的對象句柄,是復制過的,也就是在內存中復制了一個句柄,這兩個句柄指向同一個對象,所以你改變這個句柄對應的空間的數據會影響到外部的變量
雖然是復制的,但是指向的是同一個地址,當你把這個句柄指向其它對象的引用時并不會改變原來的值(例子三String),因為你用的是復制過的句柄
有道無術,術可成;有術無道,止于術
歡迎大家關注Java之道公眾號
好文章,我在看??
新人創作打卡挑戰賽發博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的面试官:Java为什么只有值传递?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux CentOS下如何确认MyS
- 下一篇: Spring Boot 2.3.3 稳定