Java中的參數(shù)傳遞

為了便于理解,會將參數(shù)傳遞分為按值傳遞和按引用傳遞。按值傳遞是傳遞的值的拷貝,按引用傳遞傳遞的是引用的地址值,所以有“在java里參數(shù)傳遞都是按值傳遞”、“引用也是按值傳遞的”這些說法。

基本數(shù)據(jù)類型作為參數(shù)傳遞

基本數(shù)據(jù)類型作為參數(shù)傳遞時都是傳遞值的拷貝。 指的是方法調用中,傳遞的是值的拷貝,無論怎么改變這個拷貝,原值是不會改變的。

也即是說實參把它的值傳遞給形參,對形參的改變不會影響實參的值。

public class Test {
    public static void main(String[] args) {
        Test test1 = new Test();
        int i = 5;
        System.out.println("調用前的i=" + i);
        test1.testPassParameter(i);
        //傳遞后,testPassParameter方法中對形參i的改變不會影響這里的i
        System.out.println("調用后的i=" + i);
    }
    public void testPassParameter(int i) {
        i = 10;//這里只是對形參的改變
        System.out.println("tpp方法中的i=" + i);
    }
}

輸出結果

調用前的i=5
tpp方法中的i=10
調用后的i=5

對象作為參數(shù)傳遞

對象作為參數(shù)傳遞時,在方法內改變對象的值,有時原對象跟著改變,而有時又沒有改變。就會讓人對“傳值”和“傳引用”產(chǎn)生疑惑。

先看看兩種情況的例子。

public class Test {
    public static void main(String[] args) {
        StringBuffer s1 = new StringBuffer("hello");
        StringBuffer s2 = new StringBuffer("hello");
        changeStringBuffer(s1, s2);
        System.out.println("s1=" + s1);
        System.out.println("s2=" + s2);
    }
    public static void changeStringBuffer(StringBuffer ss1, StringBuffer ss2) {
        ss1.append("world");
        ss2 = ss1;
    }
}

輸出結果:

s1=helloworld  
s2=hello

分析如下:

//(1)s1,s2指向字符串的地址不同,假設為地址1,地址2
StringBuffer s1 = new StringBuffer("hello");
StringBuffer s2 = new StringBuffer("hello");
image
//(2)調用changeStringBuffer方法
changeStringBuffer(s1, s2);
//調用后會將s1,s2的地址(地址1,地址2)傳給ss1,ss2,即現(xiàn)在ss1也指向地址1,ss2也指向地址2
image
//(3)ss1所指向字符串的值變?yōu)閔elloworld,調用者s1的值相應變化。
ss1.append("world");
//ss2將指向ss1指向的地址(地址1),但此時s2依舊指向地址2,s2的值在調用前后不變。
ss2 = ss1;
image

所以,s1的輸出為helloworld,s2的輸出結果為hello。

(注意,這里為了區(qū)分,s1,s2和ss1,ss2用了不同的名稱,但有時候形參與實參的名字相同,其實兩者變量是完全不同的,一個是main方法中的變量,一個是changeStringBuffer()中的變量。)

可以看出,在java中對象作為參數(shù)傳遞時,傳遞的是引用的地址,是把對象在內存中的地址拷貝了一份傳給了參數(shù)。

拓展:

基本數(shù)據(jù)類型的包裝類型在傳遞參數(shù)時其實也是“按引用傳遞的”,只是因為包裝類型變量都是不可變量,容易誤解。

String是final類型,是個特殊的類,對它的一些操作符是重載的。比如:

String str = "hello";//等價于String str=new String("hello");

 String str = "hello";
        str = str + "world";//等價于str = new String(new StringBuffer(str).append("world"));

從以上分析,現(xiàn)在可以更易理解下面的代碼:

public class Test {
    public static void fun(String str, char ch[]) {
        str = "world";
        ch[0] = 'd';
    }
    public static void main(String[] args) {
        String str = new String("hello");
        char[] ch = {'a', 'b', 'c'};
        fun(str, ch);
        System.out.println(str);
        System.out.println(ch);
    }
}

輸出結果

hello  
dbc

方法調用時,名稱相同的實參和形參并不一樣,一個是main()中的str,指向存放"hello"的內存地址。一個是fun()中的str,str="world",相當于new String("world")。String是final類型,將在堆中重新分配一個內存空間存放"world"。ch[0]='d',對象的內容發(fā)生改變。

image

所以main()中str變量存放的對象內容依然是"hello"。ch從"abc"變?yōu)?dbc"。

參考:

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy閱讀 9,656評論 1 51
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 34,628評論 18 399
  • __block和__weak修飾符的區(qū)別其實是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用,...
    LZM輪回閱讀 3,585評論 0 6
  • 患難見真情這句話實在不錯,雖然我沒有資格要求別人為我犧牲,但是當遇到困難時,尋遍四處握住那唯一一雙伸出的援手,那一...
    易張氏閱讀 140評論 0 1
  • 她說謊 說一個夜晚有二十個鐘頭那么長 說天上的星星 來回地跑 說沒有天明 天明被遺落在 一個男人的頭發(fā)上 被帶走,...
    弭路閱讀 308評論 0 2

友情鏈接更多精彩內容