String是值傳遞仍是引用傳遞

String中的坑

  最近看到一道關於String的面試題,差點讓我覺得String是值傳遞,就是下面這個例子,體驗下:<!-- more -->java

public class Demo{
    public static void main(String[] args) {
        Demo d = new Demo();
        String str = "BEA";
        d.change(str);
        System.out.println(str);
    }
    void change(String s){
        s= s.replace('A', 'E');
        s = s.toLowerCase();
    }
}

  當時一看到這個題目,我第一反應就是輸出」bee「,由於String是引用類型,其參數傳遞的方式就是引用傳遞,傳遞的是String的地址。但是答案讓個人大吃一驚,「BEA」,str根本就沒有發生變化!!面試

  難道String是值傳遞?難道String是基本類型?segmentfault

  其實都不是,後來經過查閱相應資料發現,jvm在實例化字符串時會使用字符串常量池,把str做爲參數傳入change()方法。jvm複製了一份str變量,爲了便於理解咱們叫它str'。這個時候str和str'都指向字符串常量池中的「abc」。app

  當咱們執行s = s.replace('A', 'E');
其實至關於執行了s = new String(s.replace('A', 'E'));jvm

 要理解上面這兩段話,就要從java的底層結構提及了。java的內存模型大致分爲 (細分還有方法區,和程序計數器等)。ui

1.基本類型的變量放在棧裏;

2.封裝類型中,對象放在堆裏,對象的引用放在棧裏。

<font color=red>java在方法傳遞參數時,是將變量複製一份,而後傳入方法體去執行。</font>spa

根據這些再細分一下jvm的執行過程code

1.虛擬機在堆中開闢一塊內存,並存值」BEA」。

2.虛擬機在棧中分配給str一個內存,內存中存的是1中的地址。(1指第一步)

3.虛擬機複製一份str,咱們叫str’,str和str’內存不一樣,但存的值都是1的地址。

4.將str’傳入方法體

5.方法體在堆中開闢一塊內存,並存值」BEE」。

6.方法體在堆中再次開闢一塊內存,並存值」bee」。

7.方法體將str’的值改變,存入5的內存地址。

8.方法結束,方法外打印str,因爲str存的是1的地址,全部打印結果是」BEA」。

 String的底層是一個不可變數據,因此每次給他賦新的值的時候都至關於新建了一個String對象(若是String常量池裏沒有該字符串的話),咱們能夠驗證一下。
public class Demo{
    public static void main(String[] args) {
        Demo d = new Demo();
        //經過比較str的hashCode來比較兩個對象是否爲同一對象
        String str = "BEA";
        System.out.println("第一次String的hashCode:"+str.hashCode());
        str = "bee";
        System.out.println("第二次String的hashCode:"+str.hashCode());
        //StringBuilder來試一次
        StringBuilder s = new StringBuilder("BEA");
        System.out.println("第一次StringBuilder的hashCode:"+s.hashCode());
        s.append('T');
        System.out.println("第二次StringBuilder的hashCode:"+s.hashCode());
        System.out.println("調用方法前的StringBuilder對象的值:"+s);
        d.change(s);
        System.out.println("調用方法後的StringBuilder對象的值:"+s);
    }
    void change(StringBuilder s){
        s = s.append('S');
    }
}

  看看執行的結果~對象

file

tips: hashcode並不能判斷是否爲同一個對象,可是hashcode不一樣的話確定不是同一個對象,hashcode相同的不必定是同一個對象。blog

file

關注我不會讓你失望喲~

相關文章
相關標籤/搜索