這個坑,是時候填上了~

1、背景

​  這兩天,在網上逛的時候,發現了以下的一道面試題,感受還有蠻有意思的,要是不仔細看還真容易掉到坑裏面。第一眼看起來比較繞,因此比較難理解。最終我跳出了這個坑,也想把這個跳坑的經歷分享出來。題目以下 , 請問輸出的是什麼?爲何?html

/**
 * @author hafiz.zhang
 * @description: 一個奇怪的現象
 * @date Created in 2018/7/2 22:44.
 */

public class Test {
    public static void main(String[] args) {
        String ermao = "a";
        String bb = addStr(ermao);
        System.out.println(ermao);
    }

    private static String addStr(String ermao) {
        ermao = ermao + "b";
        return ermao;
    }
}

2、結果及緣由

​   毫無疑問,這道題的答案是:a , 你答對了麼?在講解緣由以前,讓咱們想了解一點基礎知識吧:java

1. 值傳遞仍是引用傳遞?

​  其實,Java官方並無給出值傳遞仍是引用傳遞的概念。官方將Java參數傳遞類型分爲傳遞基本類型參數和傳遞引用類型參數。當參數爲基本類型(Java八大基本類型:int、short、float、double、long、boolean、byte、char)的時候,就是傳遞基本類型參數了,當參數爲封裝類型(非基本類型,如Integer、Long、Boolean等)的時候,就是傳遞引用傳遞參數了。官方文檔地址:Java參數傳遞。面試

2. Java內存模型中的堆和棧

​  從Java的底層機制來講,基本類型的變量存放在棧裏;封裝類型中,對象放在堆裏,對象的引用放在棧裏。Java在方法傳遞參數時,是將變量複製一份,而後傳入方法體去執行。數組

3. 答案是a的緣由

由於String類型在傳遞過程當中的步驟以下:oracle

  1. 虛擬機在堆中開闢一塊內存,並存值」a」。
  2. 虛擬機在棧中分配給ermao一個內存,內存中存的是1中的堆地址。
  3. 虛擬機複製一份ermao,咱們就叫ermao’好了,ermao和ermao’在棧中的內存不一樣,但此時存的值都是1的堆地址。
  4. 將ermao’傳入方法addStr中。
  5. 方法體在堆中開闢一塊新內存,並存值」ab」。
  6. 方法體將ermao’的值改變,存入5中新的堆內存地址。
  7. 方法結束,方法外打印ermao,因爲ermao存的是1中分配的堆地址,全部打印結果仍是」a」。

還不清晰?不要緊,那咱們直接上個圖會不會來得更直觀:app

4. Java到底有沒有引用傳遞  

  博友: 歸去來兮辭 說不是傳遞引用類型就是引用傳遞,Java中沒有引用傳遞。但其實 Java中並無定義值傳遞仍是引用傳遞,非基本類型的參數傳遞就是傳遞引用類型參數,但String是個特例,String類型對象的值是不可變的,由於String類是經過final修飾的char[]數組來存放結果的。每次爲String類型的變量從新賦值實際上都是新建了一個新的String實例,可是方法外部String類型變量沒有指向新的String實例,因此也就不會獲取到新的更改。這就致使了傳遞String類型參數時雖然是傳遞引用類型參數可是沒法經過參數傳遞的方式改變其變量值。歡迎你們提出不一樣意見來相互討論學習哈~

3、總結

​  經過本文咱們就理解了Java在方法傳參的整個過程。其實仍是上面那句比較重要的話Java在方法傳遞參數時,是將變量複製一份,而後傳入方法體去執行。給棒棒噠本身一波掌聲👏👏👏,點滴積累,方成大事~學習

相關文章
相關標籤/搜索