用畫小狗的方法來解釋Java中的值傳遞

來源:互聯網
上載者:User

標籤:分享   講解   div   blog   logs   9.png   變數   change   print   

 在開始看我畫小狗之前,咱們先來看道很簡單的題目: 

下面程式的輸出是什嗎?

Dog myDog = new Dog("旺財");changeName(myDog);System.out.println(myDog.getName());public void changeName(dog) {    dog.setName("小強");}

如果你的回答是“小強”,好,恭喜你答對了。下面我們改一下代碼:

Dog myDog = new Dog("旺財");changeName(myDog);System.out.println(myDog.getName());public void changeName(dog) {   dog = new Dog();   dog.setName("小強");}

是的,我只是在changeName方法裡面加了一句代碼

dog = new Dog();

這一次的輸出又是什麼呢?

  • A旺財
  • B小強

答案是 A旺財,changeName方法並沒有把myDog的名稱改了。如果你答錯了,沒關係,我要開始畫小狗了,畫完你就明白了;如果你答對了,但不太明白其中的原因,那我畫的小狗也肯定能幫到你。

myDog是什麼

首先你要搞懂,代碼裡的變數myDog是什嗎?myDog真的就是一隻狗嗎?不!不是!myDog只是一條遛狗用的狗繩!

換句話說說,myDog並不是new出來的放在堆中的對象(object)!myDog只是一個指向這個對象執行個體的引用(reference)!如果你對Java的運行時資料區域足夠瞭解,應該知道,這個引用是放在虛擬機器棧上的。

 參數傳遞

 現在你知道了,myDog只是一條繩子,但這似乎並不能解釋為什麼changeName方法沒有把myDog的名稱改為“小強”,因為按照現有的理解,dog = new Dog(),就是把我的狗繩綁到另一隻小狗身上,然後給這隻小狗起名為“小強”,就像這樣:

可事實是,myDog還是叫旺財,這是為什嗎? 
問題就出在方法調用上,當我執行changeName(myDog)這一行代碼時,myDog這條狗繩,被複製了一份,而傳入到changeName方法裡的那條狗繩(dog),就是複製出來的那一條,就像這樣:

接著執行dog= new Dog(),這一行代碼,就是把複製出來的那一條狗繩,從myDog解除綁定,重新綁到new出來的那隻小狗上,也就是後來被起名為“小強”的小狗:

而myDog還是綁在旺財身上,這也就解釋了,為什麼執行完方法出來,myDog.getName()還是旺財。而在第一段代碼裡面,我們沒有執行dog= new Dog(),也就沒有改變dog所綁的小狗,dog還是綁在旺財身上,因此dog.setName(“小強”) 就把旺財的名字改成小強了。

 string的例子

String str = "aaa";changeString(str);System.out.println(str);public void changeString(String str) {    str = "bbb";}

如果你弄懂了上面那個例子,那麼這裡應該不難理解,changeString方法裡,只是將新複製出來的引用str,指向另外一個字串常量對象“bbb”,方法體外面的str並不受影響,還是指向字串常量“aaa”,因此最終列印的還是aaa.

int的例子

int i = 1; changeInt(i); System.out.println(i); public void changeInt(int i) { i = 2; }

對於基礎資料型別 (Elementary Data Type),他們沒有引用,但是不要忘了,調用函數時,複製的動作還是會做的,執行changeInt(i)時,會將 i 複製到一個新的int上,傳給changeInt方法,因此不管changeInt內部對入參做了什麼,外面的 i 都不會受影響。最後列印出來的還是1.

值傳遞和引用傳遞

上面提到的參數傳遞過程中的複製操作,說白了,就是 = 操作。把上面那個int例子,做一下方法內聯,其實就是這樣:

int i = 1;// 方法內聯,相當於執行changeInt方法int j = i; // 建立一個和i一樣的變數j = 2; //修改j的值,i不變System.out.println(i);

對於基礎資料型別 (Elementary Data Type),= 操作將右邊的變數(R_VALUE)完整的複製給左邊的變數(L_VALUE),而對於對象,準確的說,應該是指向對象的引用(就像上面說的myDog),= 操作同樣也是將右邊的引用完整的複製給左邊的引用,兩者指向同一個對象執行個體。 
這個 = 操作,是值傳遞和引用傳遞的根本差別,這也導致了值傳遞和引用傳遞有以下直觀上的差別:

  • 如果參數是值傳遞,那麼調用者(方法體外部)和被調用者(方法體內部)用的是兩個不同的變數,方法體裡面對變數的改動不會影響方法體外面的變數。而之所以在Java可以在方法體內部改變方法體外部的對象,是因為方法體內部拿到了對象的引用,但是這個引用是和方法體外部的引用屬於兩個不同的引用的,方法體內部的引用指向別的對象,不會導致方法體外部的引用也指向別的對象。
  • 如果參數是引用傳遞,那麼調用者(方法體外部)和被調用者(方法體內部)用的是兩個相同的變數,方法體裡面對變數的改動會影響方法體外面的變數。

Java的變數都不是對象

通過上面的講解,你也知道了一個很重要的點:Java裡面的變數,要麼是基礎資料型別 (Elementary Data Type),要麼是指向對象執行個體的參考型別(狗繩),絕對不會是一個對象(狗)。

用畫小狗的方法來解釋Java中的值傳遞

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.