轉自公眾號:程式控
面試官愛問的一個基礎問題:Java是值傳遞還是參考傳遞?
想必大家都對這個問題都有自己的看法,那到底事實是怎樣的,我們又該如何回答面試官這個問題呢?今天咱們就來好好分析一波
值傳遞?參考傳遞?
首先,我們得先知道什么叫值傳遞,什么叫參考傳遞,知道這個才能理解Java到底如何做的,若想理解這兩種傳遞需要先理解形式引數和實際引數兩個概念
形式引數: 定義函式時使用的引數,用來接收函式傳入引數,比如我們寫個函式,函式中的引數為形式引數
(String str) { System..println(str)}
實際引數: 我們呼叫函式時,函式名后面括號中的引數稱為實際引數,如下面例子所示
(String[] args) {
A a = A()a.test()}
可以發現,當呼叫一個有參函式的時候,會把實際引數傳遞給形式引數;于是這個傳遞的程序便有兩種情況,即值傳遞和參考傳遞
值傳遞就是把引數的值給你,呼叫函式時將實際引數復制一份傳遞到函式中,這樣函式內部對引數內部進行修改不會影響到實際引數;而參考傳遞就不一樣了,它直接把引數的實際地址給呼叫函式了,函式內部可直接修改該地址內容,會影響到實際引數
我來舉個例子,我司有一個資料庫A,僅允許內部人員操作,現在有個專案需要和別的公司合作,該資料庫的資料需要交給合作公司一份,我總不能直接把我司資料庫A地址給他們,讓他們直接連我們資料庫A吧,他們要是刪庫跑路了,那我boss豈不要殺我祭天了
所以這個時候,把我司資料庫表資料拷貝一份到一個新的資料庫B,合作公司可以看這個資料庫B資料,他們也可以隨意操作,不會影響我司資料庫
這個操作就類似于值傳遞,如果合作公司直接操作我司資料庫,就類似于參考傳遞了,這下大家應該曉得兩者之別了
Java值傳遞還是參考傳遞?
我們了解了值傳遞和參考傳遞的概念,那Java中到底是哪種傳遞方式呢?我們來看代碼分析
(String[] args) {
Fans fans = Fans()t = fans.test(t)System..println(+ t) }
(t) {
t = System..println(+ t) }
//輸出
In testIn main
上述代碼,在main中定義t的值是1,在函式test中修改了引數t的值為2,這個結果是不是很容易分析出來了呢?test函式并未改變傳入的t的值,那按照上面我們的介紹是不是可以得出結論:Java中是值傳遞
有的人可能會質疑,你傳入的引數t是基本型別,你若傳入參考物件型別,那肯定就會改變物件內容了,OK,再來看一段參考型別代碼
= String = (Fans fans) {
fans.= fans.= System..println(+ fans.++fans.)}
(String[] args) {
Fans fa = Fans()fa.test(fa)System..println(+ fans.getA()++fans.getB())}
//輸出
In testABnewFans
In mainABnewFans
哎啊,輸出結果竟然一樣了,也就是傳入的fans物件被函式test修改了,那這樣是不是又變成了參考傳遞了?
于是得出結論,基本型別是值傳遞,參考型別是參考傳遞?事實是這個樣子嗎,我們再來通過String這個參考型別實驗下
(String t) {
t = System..println(+ t)}
(String[] args) {
Fans fans = Fans()String tt = fans.test(tt)System..println(+ t)}
//輸出
In test:關注公眾號
In main:Java技術堆疊
啊,這,咋肥事,傳遞的引數值并未修改,怎么又變成值傳遞了
上述三個例子表現結果各有差異,到底結論是什么呢?一起來分析下
第一個傳入的是基本型別,基本型別指向的就是數值,傳遞類似于賦值操作,不會對原數值產生影響,就是類似于a=10,b=a,b=20這種,并不會使a變為20;
第二個參考物件傳入的是參考型別fans的地址的值,傳入的原引數fa指向地址0x123456,所以函式test的引數fans也指向0x123456,函式內部對參考fans進行修改,于是修改了0x123456地址的值,造成外部改變
第三個參考物件是String型別,同樣傳入的是原引數tt的指向地址0x123456,函式test引數t也是指向0x123456的值,那為什么這個和第二個結果不一樣的嘞?重點在于 t="關注公眾號"; 這一句本來想嘗試著使內容"Java技術堆疊"改變成"關注公眾號",但是無奈,String型別是static final型別的,這個大家應該曉得的不,不曉得的該去補課讀讀String的原始碼了,于是變成了 t=new String("關注公眾號"),t指向了另一個地址,這個地址的內容是"關注公眾號",所以原來的參考tt還是指向原來的地址0x123456,并未改變
有的同學可能會提出問題了,為什么第二個可以改變這個地址的內容,第三個不行?很明顯啊,String是final的,不可修改,而第二個可以直接修改該地址的內容;那問題又來了,既然這樣,還能叫值傳遞嗎?
告訴你,就是值傳遞,因為我們第二個的驗證方法不對,你如果在函式的第一行加上個fans = new Fans();你看看它還輸出啥,這就變成和第三個String類似的道理了,改變了函式引數的指向位置,函式外部和函式內部輸出就不一樣了,函式內部也就不會影響外部了;如果按照應參考傳遞,即使加了這一句,也應該是函式內外都是輸出一樣的,況且,這也有悖于參考傳遞的會改變傳入引數的概念
思考
值傳遞和參考傳遞并不是按照傳遞的內容來區分的,傳遞的是參考的并不一定的參考傳遞,根據定義結果來區分;
在Java中用的是值傳遞(記好咯,下次面試別回答錯了)
在其它方法里面改變參考型別的值都是通過參考改變的,當傳遞參考物件的時候,傳遞的是復制的參考的物件句柄,是復制過的,也就是在記憶體中復制了一個句柄,這兩個句柄指向同一個物件,所以你改變這個句柄對應的空間的資料會影響到外部的變數
雖然是復制的,但是指向的是同一個地址,當你把這個句柄指向其它物件的參考時并不會改變原來的值(例子三String),因為你用的是復制過的句柄
最后嘮叨
贈人玫瑰,手留余香
如果本文幫助到你了,說明我的下個文章也會幫到你,留個關注吧,么么噠
近期熱文推薦:
1.Java 15 正式發布, 14 個新特性,重繪你的認知!!
2.終于靠開源專案弄到 IntelliJ IDEA 激活碼了,真香!
3.我用 Java 8 寫了一段邏輯,同事直呼看不懂,你試試看,,
4.吊打 Tomcat ,Undertow 性能很炸!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/206047.html
標籤:Java
上一篇:awk實作類sql的join操作
