Java 的參數傳遞

一、傳值和傳址(引用)

Java 的參數傳遞分爲傳遞基本數據類型(傳值)和傳遞引用數據類型(傳址)

public class Demo {

    public void fun(Test test, int i) {
        test.name = "test2";
        i = 2;
        System.out.println(i);
    }

    public static void main(String[] args) {
        Demo demo = new Demo();
        Test test = new Test();
        int i = 1;
        demo.fun(test, i);
        System.out.print(test.name + " and " + i);
    }
}

class Test {
    String name = "test";
}
2
test2 and 1

對於基本數據類型,當我們修改傳遞的值,原來的值不會改變,所以傳遞的是值的拷貝。值的拷貝在一塊兒新的內存中。

對於引用數據類型,當我們通過傳遞的引用變量修改對象的屬性,原引用指向的對象也將改變,所以沒有將對象的數據拷貝傳遞,傳遞的是指向對象的引用變量,即對象的地址。當然,引用變量是值傳遞,引用變量的拷貝在一塊兒新的內存中。

正常來說,傳值更符合正常思路。我把值傳給你,你使用它,不會影響我的值。

因爲傳址的特點,可以將大數據存放到對象中,傳遞對象引用,減少參數(局部變量表)的大小以提高棧幀的空間利用率。

二、String 的參數傳遞

public class Demo {

    String str = new String("hello");
    char[] ch = {'a', 'b', 'c'};

    public void fun(String str, char[] ch) {
        str = "world";
        ch[0] = 'd';
    }

    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.fun(demo.str, demo.ch);
        System.out.print(demo.str + " and ");
        System.out.print(demo.ch);
    }
}
hello and dbc
  1. 局部變量 str 和全局變量 str 這 2 個名稱相同變量,但內存位置不同的值都是 0x1001(假設)
  2. 對象 test 調用 fun 方法,將實參 test.str(全局變量 str 存放對象 "hello" 的內存地址)和 test.ch(全局變量 ch 存放字符數組對象的內存地址),傳給 fun 方法的形參 str 引用和 ch 引用。
  3. 局部變量 str 存放對象 "hello" 的內存地址。"world" 匿名對象, str = "world"; 等價於 str = new String("world") ,相當於將在堆中重新分配一個內存空間存放 "world",局部變量 str 指向 "world"。局部變量 str 的生命週期和方法相同,只是名稱和全局變量 str 相同

以上兩步操作在 JVM 中如下圖所示,內存地址爲假設。

image

  1. char ch[] 與 char[] ch 等價。語句 ch[0] = 'd'; 將替換字符數組對象中下標爲 0 的字符,即改變了對象的內容。test.str 沒有改變,還是 "hello",test.ch 從 "abc" 改爲 "dbc"。

IDEA 調試圖如下:

image

2.1、理解引用存放地址

Book a == new Book();// 對象 1
Book b == new Book();// 對象 2
b = a;

問:那個對象會被回收? 答:對象 2,因爲將引用 a 中存放對象 1 的地址賦值給了引用 b,所以引用 b 將 “指向” 對象 1,對象 2 將被回收。

三、總結

可以將地址視爲值,所以傳值和傳址都可以視爲傳值。

四、延伸閱讀

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章