問題源于在Java中使用對象作為參數(shù),按照C++的思路進(jìn)行調(diào)試,發(fā)現(xiàn)結(jié)果與C++中并不相同。
導(dǎo)致該問題的原因是Java與C++對于對象的解釋是不相同的。
在C++中對象作為參數(shù)采用的是“傳值調(diào)用”,當(dāng)實(shí)參通過形參傳遞時(shí),會調(diào)用對象(實(shí)參)的拷貝構(gòu)造函數(shù)(如果沒有顯式的定義拷貝構(gòu)造函數(shù),將自動調(diào)用默認(rèn)拷貝構(gòu)造函數(shù),它的功能是將實(shí)參中的對象原樣的拷貝到形參中,這里牽扯到深拷貝和淺拷貝的問題,但不影響對本問題的分析。),函數(shù)實(shí)際操作的是該對象的拷貝,并不影響原對象。
而在Java中,對象作為參數(shù)時(shí),形參是被初始化為實(shí)參對象的引用。如果對形參進(jìn)行操作會影響到實(shí)參(原對象)。這有點(diǎn)類似于C++中的”引用調(diào)用“,但并非如此,Java中采用的仍然是”傳值調(diào)用“。而導(dǎo)致結(jié)果不同的原因是,Java與C++中對對象名的解釋是不同的。在C++中“類”和“對象”的關(guān)系可以類比為“類型”和“變量”之間的關(guān)系,對象在定義的時(shí)候即分配了內(nèi)存空間,它是實(shí)實(shí)在在存在的。而在Java中,對象定義時(shí)只是定義了“對象變量”,它只是指向一個(gè)對象,當(dāng)使用new操作符時(shí)才會構(gòu)造指向的這個(gè)對象。Java中的對象名有點(diǎn)像C++中指向?qū)ο蟮闹羔槪?dāng)作為參數(shù)傳遞時(shí),傳遞的是該對象在內(nèi)存中的地址。
在C++和Java中String類的對象str的存儲方式分別如下:

以Java中對象作為參數(shù)傳遞的例子分析一下:
1 public class Test1 { 2 public static void main(String[] args) { 3 StringBuffer str = new StringBuffer("Hello "); 4 System.out. 按照上面的分析,將str傳遞給strBuf 時(shí),是將Hello存儲的地址傳遞過去,那么輸出結(jié)果是:
Before change, str = HelloAfter changeData, str = Hello World!
將上面的代碼修改一下,如下:
1 public class Test2 { 2 public static void main(String[] args) { 3 StringBuffer str = new StringBuffer("Hello "); 4 System.out.println("Before change, str = " + str); 5 changeData(str); 6 System.out.println("After changeData, str = " + str); 7 } 8 9 public static void changeData(StringBuffer strBuf) {10 strBuf = new StringBuffer("Hi ");11 strBuf.append("World!");12 }13 } 按照上面的分析,將str傳遞給strBuf 時(shí),strBuf 與str都將存放Hello的存儲地址,如下圖:

然后當(dāng)執(zhí)行完strBuf = new StringBuffer("Hi "); 后,以上關(guān)系將變成:

此時(shí)strBuf 中存放的不再是Hello的地址,而是Hi的地址,new操作符操作成功后總會在內(nèi)存中新開辟一個(gè)存儲區(qū)域。
當(dāng)執(zhí)行strBuf.append("World!"); 這句時(shí),此時(shí)操作的將是Hi,而不是Hello,那么結(jié)果將變成:

最后輸出結(jié)果如下:
Before change, str = HelloAfter changeData(n), str = Hello
|
新聞熱點(diǎn)
疑難解答
圖片精選