java:陣列拷貝與“擴容”
阿新 • • 發佈:2021-01-19
1、前述
java裡面,陣列的“擴容”與“拷貝”,藉助“拷貝”實現“動態陣列”
java裡面的陣列 int arr[]= new int[10]; arr在棧上 new出來的東西在堆上
所謂的陣列的擴容,其實是物件所指向的記憶體發生了變化,導致陣列“看起來長度變化”,並不是真正意義上的“動態陣列”
拷貝前後,記憶體分離 深拷貝
反之,淺拷貝
2、實現
1、new一個新array
//way 1 new一個新array int arr[] = new int[]{1,2,3,4,5,6,7,8,9,10}; int brr [] = new int[arr.length*2]; for(int i = 0;i<arr.length;i++){ brr[i] = arr[i]; } arr = brr; System.out.println("brr = arr"+Arrays.toString(arr)); if (arr==brr) System.out.println("共用地址"); else System.out.println("地址不同");
2 Object類的 clone方法 克隆,並不會改變長度
//way2 clone方法 克隆,並不會改變長度 int crr[] = new int[]{1,2,3,4,5,6,7,8,9,10}; int drr[] =crr.clone(); System.out.println("clone"+Arrays.toString(drr)); if (crr==drr) System.out.println("共用地址"); else System.out.println("地址不同"); //Object 類的clone方法 該方法是類 Object 中的方法,可以建立一個有單獨記憶體空間的對像。故而是地址不同的
3、Arrays.copyOf()方法 底層實現是System.arrayCopy()
int err[]= new int[]{1,2,3,4,5,6,7,8,9,10}; int frr[]=Arrays.copyOf(err,err.length*2); System.out.println("Arrays.copyOf"+Arrays.toString(frr)); if (err==frr) System.out.println("共用地址"); else System.out.println("地址不同"); /* Arrays.copyOf()底層實現,是 System.ArrayCopy()方法 //其機制是先new一個newLength的copy陣列,藉助System.ArrayCopy()把老陣列內容拷貝到新陣列,最後返回新陣列 //所以,是new了一塊地址 當然記憶體是不同的 原始碼實現 copyOf(int[] original, int newLength) { int[] copy = new int[newLength]; System.arraycopy(original, 0, copy, 0, Math.min(original.length, newLength)); return copy; } * */
4、System.ArrayCopy() native方法 ,看不了實現
int grr[] = new int[]{1,2,3,4,5,6,7,8,9,10};
int hrr[] = new int[10];
//方法的src dest陣列必須非空 必須宣告空間 不然報錯
System.arraycopy(grr,0,hrr,0,grr.length);
System.out.println("System.Arraycopy"+Arrays.toString(hrr));
if (grr==hrr)
System.out.println("共用地址");
else
System.out.println("地址不同");
//System.ArrayCopy() 是native方法,無法檢視其原始碼
5、淺拷貝的一種實現
int irr[] = new int[]{1,2,3,4,5,6,7,8,9,10};
int jrr[] = irr;
System.out.println(" int jrr[] = irr;"+Arrays.toString(hrr));
if (irr==jrr)
System.out.println("共用地址");
else
System.out.println("地址不同");
//其實這和way1是一樣的,way1是new了塊新記憶體,但原來的陣列指向了新的記憶體 記憶體是有共用的
//這塊,是新陣列沒有new出地址,直接指向老陣列的地址
上面幾個方法,對於一維陣列是深度拷貝,即記憶體分離。但對於二維陣列或n維, 可以理解為定義了一個二維陣列,記憶體在堆中開闢,其中一維是共享地址的,另一維是記憶體獨立的,屬於淺拷貝。 可以通過迴圈,實現記憶體分離的深度拷貝