09 January 2012
不知道大家有沒有發現,
把物件A,設值給B,
當B的值改,A也會改!?!?!?!?!?

如下:
ArrayList<String> A = new ArrayList<String>();
A.add("KenYang");
ArrayList<String> B= A;



這時候如果我們去印出B的長度,
System.out.println(B.size());
那會是甚麼?
答案會是1,這無庸置疑,很基本的常識。


可是如果我把B的第0項刪除,在印出B的長度呢?
B.remove(0);
不用想,一定變成0。


那這時候,A的長度呢? 一般人可能會以為是1,
在C++的觀念,的確如此,的確會是1,
但在java不是...
可以印出來看看!
System.out.println(A.size());
答案會是0!


這是為什麼呢? 為什麼只是修改了B的值,
A也變了??

這是因為,在java中,非primitive的資料型態,
都屬於物件,都是參考!!! (甚麼是參考? 可以去我先前PO的文章看看)
簡單的說就是別名。
但Java的參考概念就很像C++的pointer!!! (記錄著該物件的位址)


下面用圖片來解釋,上面code的行為,
下面圖一的行為就是,

先宣告A,再設值進去。
我們可以從圖發現,A是去參考記憶體位址為0000的物件!!!!

圖一


那麼這時候,把A的值丟給B呢?
在記憶體中的表現會是怎樣?
A=B;
如圖二。
會發現B,也是去參考記憶體位址為0000的物件!!!
A和B都是記錄著該物件的記憶體位址!!!

圖二


所以從圖中應該可以了解上面的行為了吧?
為什麼B把第0項刪除,
結果A也變了呢?
就是因為在JAVA非primitive都是參考的關係!!!

嗯! 那有人可能會疑問!!!
咦? String 也是非primitive的資料型態阿
可是為什麼下面的例子,B改,A卻沒改呢?


這就要用到先前某篇講解java拆箱(unboxing)、裝箱(boxing)的概念了!
那關java拆箱(unboxing)、裝箱(boxing)的甚麼事呢?
還是不了解為什麼兩個都是String的物件,怎麼B改,A卻沒改呢?
來看下面的小例子,
String A = "ken";
String B = A;
B = "yang";
System.out.println(A);
為什麼不是印出yang呢?
都是primitive阿,
原因就是自動裝箱(auto-boxing),
上面的行為,在Compiler中,
B="yang"
會被轉換成
B = new String("yang");
這時候他就是全新的物件了!
因此不會改到原本的值!!!!!



在Java中的複製,
想要做到真正的複製,
得靠clone了。
clone有機會再說吧!










blog comments powered by Disqus