面試官:String是值傳遞仍是引用傳遞

面試官:String是值傳遞仍是引用傳遞

本文已收錄GitHub,更有互聯網大廠面試真題,面試攻略,高效學習資料等java

把一個String類型的參數傳入方法,並在方法內改變了引用的值。 而後在方法外使用這個值,發現這個String仍是以前的值,並無改變。git

這裏要向你們介紹一下,你們都知道java在傳參時分爲值 傳遞 和 引用傳遞 。參數爲基本類型時是值傳遞, 參數爲封裝類型時是引用傳遞。例如:github

基本類型參數面試

public class Test {
    public static void main(String[] args) {
        int num = 0 ;
        changeNum(num);
        System.out.println("num="+num);
    }

    private static void changeNum(int num) {
        num = 1;
    }
}

打印的結果是num=0。ide

封裝類型參數學習

public class Test {
    public static void main(String[] args) {
        Product p = new Product();
        p.setProName("before");
        p.setNum(0);
        changeProduct(p);
        System.out.println("p.proName="+p.getProName());
        System.out.println("p.num="+p.getNum());
    }

    private static void changeProduct(Product p) {
        p.setProName("after");
        p.setNum(1);
    }
}

class Product {
    private int num;
    private String proName;

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getProName() {
        return proName;
    }

    public void setProName(String proName) {
        this.proName = proName;
    }
}

運行的結果是:p.proName=after和p.num=1 。this

上面的兩個例子是明顯的值傳遞和引用傳遞。可是若是參數是String類型呢?咱們看一下具體的例子:code

public class Test {
    public static void main(String[] args) {
        String str = "ab";
        changeString(str);
        System.out.println("str="+str);
    }

    private static void changeString(String str) {
        str = "cd";
    }
}

你們猜一下運行結果是什麼呢?按照前面的例子,String應該是一個封裝類型,它應該是引用傳遞,是能夠改變值得, 運行的結果應該是」cd」。咱們實際運行一下看看,對象

str=ab,這如何解釋呢?難道String是基本類型?也說不通呀。blog

這就要從java底層的機制講起了,java的內存模型分爲 堆 和 棧 。

  1. 基本類型的變量放在棧裏;
  2. 封裝類型中,對象放在堆裏,對象的引用放在棧裏。

java在方法傳遞參數時,是將變量複製一份,而後傳入方法體去執行。 這句話是很難理解的,也是解釋這個 問題的精髓。咱們先按照這句話解釋一下基本類型的傳遞

  • 虛擬機分配給num一個內存地址,而且存了一個值0.
  • 虛擬機複製了一個num,咱們叫他num’,num’和num的內存地址不一樣,但存的值都是0。
  • 虛擬機講num’傳入方法,方法將num’的值改成1.
  • 方法結束,方法外打印num的值,因爲num內存中的值沒有改變,仍是0,因此打印是0.

咱們再解釋封裝類型的傳遞:

  • 虛擬機在堆中開闢了一個Product的內存空間,內存中包含proName和num。
  • 虛擬機在棧中分配給p一個內存地址,這個地址中存的是1中的Product的內存地址。
  • 虛擬機複製了一個p,咱們叫他p’,p和p’的內存地址不一樣,但它們存的值是相同的,都是1中Product的內存地址。
  • 將p’傳入方法,方法改變了1中的proName和num。
  • 方法結束,方法外打印p中變量的值,因爲p和p’中存的都是1中Product的地址,可是1中Product裏的值發生了改變, 因此,方法外打印p的值,是方法執行之後的。咱們看到的效果是封裝類型的值是改變的。

最後咱們再來解釋String在傳遞過程當中的步驟:

  • 虛擬機在堆中開闢一塊內存,並存值」ab」。
  • 虛擬機在棧中分配給str一個內存,內存中存的是1中的地址。
  • 虛擬機複製一份str,咱們叫str’,str和str’內存不一樣,但存的值都是1的地址。
  • 將str’傳入方法體
  • 方法體在堆中開闢一塊內存,並存值」cd」
  • 方法體將str’的值改變,存入5的內存地址
  • 方法結束,方法外打印str,因爲str存的是1的地址,全部打印結果是」ab」

這樣咱們理解了java在方法傳參的整個過程。其實仍是上面那句比較重要的話 java在方法傳遞參數時,是將變量複製一份,而後傳入方法體去執行。

相關文章
相關標籤/搜索