目錄
- 前言
- 深拷貝與淺拷貝
- 方式一:System.arraycopy()
- 陣列元素為基本型別
- 記憶體分析
- 陣列元素為參考型別
- 記憶體分析
- 方式二:clone()方法
- 陣列元素為基本型別
- 記憶體分析
- 陣列元素為參考型別
- 記憶體分析
- 方式三:Arrays.copyOf()方法
- 方式四: for回圈
- 陣列元素為基本型別
- 記憶體分析
- 陣列元素為參考型別
- 記憶體分析
- 參考
前言
本文大部分內容出自:https://s-ajie.blog.csdn.net/article/list/3
筆者對相關內容進行了整理和補充,
深拷貝與淺拷貝
- 淺拷貝:僅僅是指向被復制的記憶體地址,如果原地址發生改變,那么淺拷貝出來的物件也會相應的改變,
- 深拷貝:在計算機中開辟一塊新的記憶體地址用于存放拷貝的物件,
因此,深拷貝和淺拷貝最根本的區別在于是否真正獲取一個物件的復制物體,而不是參考,
方式一:System.arraycopy()
效率最高,
進入System類,發現arraycopy()是一個本地方法:
public static native void arraycopy(Object src,int srcPos,Object dest,int destPos,int length);
陣列元素為基本型別
import java.util.Arrays;
public class TestDemo {
public static void main(String[] args) {
int[] array1 = new int[]{1,2,8,7,6};
int[] array2 = new int[array1.length];
System.arraycopy(array1, 0, array2, 0, array1.length);
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
System.out.println("=========================");
array2[0] = 100;
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
}
}
輸出結果:
array1 = [1, 2, 8, 7, 6]
array2 = [1, 2, 8, 7, 6]
=========================
array1 = [1, 2, 8, 7, 6]
array2 = [100, 2, 8, 7, 6]
由結果可以看出,當對復制陣列的某個元素進行改變時,并不影響被復制陣列對應元素,即對于基本資料型別來說System.arraycopy() 方法是深拷貝,
記憶體分析

陣列元素為參考型別
class TestArray{
private int val = 10;
public void setVal(int val){
this.val = val;
}
public int getVal(){
return this.val;
}
}
public class TestDemo {
/**陣列輸出方法 */
public static void printArray(TestArray[] array){
for(int i = 0;i < array.length;i++){
System.out.print(array[i].getVal()+" ");
}
System.out.println();
}
public static void main(String[] args) {
TestArray[] array1 = new TestArray[3];
// 陣列參考賦值
for (int i = 0; i < array1.length; i++){
array1[i] = new TestArray();
}
TestArray[] array2 = new TestArray[array1.length];
// 陣列System.arraycopy()方法復制
System.arraycopy(array1,0,array2,0,array1.length);
printArray(array1);
printArray(array2);
System.out.println("==========");
array2[0].setVal(100);;
printArray(array1);
printArray(array2);
}
}
輸出結果:
10 10 10
10 10 10
==========
100 10 10
100 10 10
由結果可以看出,當對復制陣列的某個元素進行改變時,被復制陣列對應元素也隨之改變,即對于參考資料型別來說 System.arraycopy() 方法是淺拷貝,
記憶體分析

方式二:clone()方法
效率次高,
陣列元素為基本型別
import java.util.Arrays;
public class TestDemo {
public static void main(String[] args) {
int[] array1 = new int[]{1, 2, 8, 7, 6};
int[] array2 = new int[array1.length];
array2 = array1.clone();
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
System.out.println("======================");
array2[0] = 100;
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
}
}
輸出結果:
array1 = [1, 2, 8, 7, 6]
array2 = [1, 2, 8, 7, 6]
======================
array1 = [1, 2, 8, 7, 6]
array2 = [100, 2, 8, 7, 6]
由結果可以看出,當對復制陣列的某個元素進行改變時,并不影響被復制陣列對應元素,即對于基本資料型別來說clone()方法實作陣列拷貝也屬于深拷貝,
截取上面程式的一小段,稍加改變:
int[] array1 = new int[]{1, 2, 8, 7, 6};
int[] array2 = new int[array1.length];
System.out.println("array1 的地址是: " + array1);
System.out.println("array2 的地址是: " + array2);
array2 = array1.clone();
System.out.println("array2 的地址是: " + array2);
輸出結果:
array1 的地址是: [I@7852e922
array2 的地址是: [I@4e25154f
array2 的地址是: [I@70dea4e
可以看到,剛開始通過int[] array2 = new int[array1.length]陳述句申請的陣列和array2 = array1.clone()陳述句產生的陣列并不是同一個陣列,
通過查看clone()方法的原始碼,對于clone()方法的介紹,總綱是
Creates and returns a copy of this object.
創建并回傳此物件的副本,
這就可以理解為什么array2陣列克隆前后指向不同的地址了,
記憶體分析

陣列元素為參考型別
class TestArray{
private int val = 10;
public void setVal(int val){
this.val = val;
}
public int getVal(){
return this.val;
}
}
public class TestDemo {
/**陣列輸出方法 */
public static void printArray(TestArray[] array){
for(int i = 0;i < array.length;i++){
System.out.print(array[i].getVal()+" ");
}
System.out.println();
}
public static void main(String[] args) {
TestArray[] array1 = new TestArray[3];
// 陣列參考賦值
for (int i = 0; i < array1.length; i++){
array1[i] = new TestArray();
}
TestArray[] array2 = new TestArray[array1.length];
// 陣列clone()方法復制
array2 = array1.clone();
printArray(array1);
printArray(array2);
System.out.println("==========");
array2[0].setVal(100);;
printArray(array1);
printArray(array2);
}
}
輸出結果:
10 10 10
10 10 10
==========
100 10 10
100 10 10
由結果可以看出,當對復制陣列的某個元素進行改變時,被復制陣列對應元素也隨之改變,即對于參考資料型別來說clone()方法是淺拷貝,
記憶體分析

方式三:Arrays.copyOf()方法
進入Arrays類,發現其copyOf()方法的底層呼叫的是System.arraycopy()方法,因此該處將不再贅述其底層原理,
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
該法的效率為第三高,
方式四: for回圈
效率最低,
陣列元素為基本型別
import java.util.Arrays;
public class TestDemo {
public static void main(String[] args) {
int[] array1 = new int[]{1, 2, 8, 7, 6};
int[] array2 = new int[array1.length];
for (int i = 0;i < array1.length;i++){
array2[i] = array1[i];
}
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
System.out.println("======================");
array2[0] = 100;
System.out.println("array1 = " + Arrays.toString(array1));
System.out.println("array2 = " + Arrays.toString(array2));
}
}
輸出結果:
array1 = [1, 2, 8, 7, 6]
array2 = [1, 2, 8, 7, 6]
======================
array1 = [1, 2, 8, 7, 6]
array2 = [100, 2, 8, 7, 6]
由結果可以看出,當對復制陣列的某個元素進行改變時,并不影響被復制陣列對應元素,即對于基本資料型別來說for回圈陳述句是深拷貝,
記憶體分析

陣列元素為參考型別
class TestArray{
private int val = 10;
public void setVal(int val){
this.val = val;
}
public int getVal(){
return this.val;
}
}
public class TestDemo {
/**陣列輸出方法 */
public static void printArray(TestArray[] array){
for(int i = 0;i < array.length;i++){
System.out.print(array[i].getVal()+" ");
}
System.out.println();
}
public static void main(String[] args) {
TestArray[] array1 = new TestArray[3];
// 陣列參考賦值
for (int i = 0; i < array1.length; i++){
array1[i] = new TestArray();
}
TestArray[] array2 = new TestArray[array1.length];
// 陣列for回圈復制
for (int i = 0; i < array2.length; i++){
array2[i] = array1[i];
}
printArray(array1);
printArray(array2);
System.out.println("==========");
array2[0].setVal(100);;
printArray(array1);
printArray(array2);
}
}
輸出結果:
10 10 10
10 10 10
==========
100 10 10
100 10 10
由結果可以看出,當對復制陣列的某個元素進行改變時,被復制陣列對應元素也隨之改變,即對于參考資料型別來說for回圈陳述句是淺拷貝,
記憶體分析

參考
[1]https://www.cnblogs.com/mikeCao/p/8710837.html
[2]https://s-ajie.blog.csdn.net/article/details/79939248
[3]https://www.nowcoder.com/questionTerminal/e7c2d52c9cf0476bbba6aae6713dd303
[4]https://blog.csdn.net/qq_40178464/article/details/79941843
[5]https://s-ajie.blog.csdn.net/article/details/79942319
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/255563.html
標籤:java
上一篇:單例模式
下一篇:redis五大資料結構和使用場景
