Java中的陣列互相賦值
本文探討Java中陣列中的賦值問題。在探討這個問題之前必須先弄懂一件事,Java中的陣列到底是什麼東西?是類,是物件,還是什麼其他奇奇怪怪的東西。答案是:Java中的陣列本質上是物件。但是這個物件不是通過某個類例項化來的,而是JVM建立的,這也就不難解釋對於一個數組物件arr,我們可以直接通過arr.length訪問陣列的長度。
現在我們知道了Java中陣列本質上是物件,那麼我們來看一下這樣的程式碼合理不合理:
int[] a = {1,2,3}; int[] b = new int[3]; b = a; for(int i = 0; i < a.length; i++) a[i] = 0;
我們本來的想法是把a陣列的值賦值給b,然後將a陣列清零,但是我們會發現a,b陣列都被清零了。
既然陣列本質是物件,那麼我們來分析一下這兩句程式碼在Java記憶體模型中發生了什麼。
int[] a = {1,2,3};的時候,堆中會生成一個對應的物件,a會指向這個物件,然後int[] b = new int[3];的時候,b也會指向這個物件。那麼比如我們在對a[0]進行修改的時候,實際上是對堆中物件做出了修改。b陣列仍然是指向這個堆中物件的,當然b陣列的值也改變了。
說到這裡已經顯而易見了,這樣實際上不太合理,比較兩個引用都是指向同一個堆中物件,其中一個修改必然會導致另一個的修改。
那麼陣列的賦值究竟應該怎麼做呢?
一、使用for迴圈
int[] a = {1,2,3};
int[] b = new int[3];
for(int i = 0; i<a.length; i++)
b[i] = a[i];
這樣可以實現賦值操作,而且靈活性不錯,但是效率是個問題。
二、使用Object的clone()
既然陣列本質是物件,那麼他就有clone()方法。我們可以使用clone()方法進行復制:
int[] a={1,2,3};
int[] b=(int[]) a.clone();//別忘了強制型別轉換
三、使用System的靜態方法arraycopy()System提供了一個靜態方法arraycopy(),原型如下:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源陣列
srcPos:源陣列要複製的起始位置
dest:目的陣列
destPos:目的陣列放置的起始位置
length:複製的長度
我們可以用它來進行陣列之間的複製:
int[] a ={1,2,3};
int[] b = new int[3];
System.arraycopy(a,0,b,0,3);
這個方法效率很高,而且具有一定的靈活性。許多基於陣列實現的Java的集合類底層在陣列複製的時候都是使用這個方法。