詳解Java數(shù)組的四種拷貝方式
深拷貝與淺拷貝的區(qū)別
假設現(xiàn)在有原數(shù)組A以及拷貝后的數(shù)組B,若是改變A中的某一個值,B數(shù)組隨之相應的發(fā)生變化的拷貝方式稱為淺拷貝,反之B數(shù)組不受影響,則稱為深拷貝;
簡單總結(jié)一下兩者的概念:
深拷貝:拷貝后,修改原數(shù)組,不會影響到新數(shù)組;
淺拷貝:拷貝后,修改原數(shù)組,新數(shù)組也會相應的發(fā)生改變;
1. for循環(huán)進行拷貝
拷貝數(shù)值類型
當數(shù)組中存放的元素為基本數(shù)據(jù)類型時,此時發(fā)生的是深拷貝;
//1. for循環(huán)拷貝 (拷貝數(shù)值類型) ---深拷貝
public static void main(String[] args) {
int[] A = {1,2,3,4,5};
int[] B = new int[A.length];
for (int i = 0; i < A.length; i++) {
B[i] = A[i];
}
System.out.println("A : " + Arrays.toString(A)); //A : [1, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [1, 2, 3, 4, 5]
System.out.println("===========修改后===========");
A[0] = 100;
System.out.println("A : " + Arrays.toString(A)); //A : [100, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [1, 2, 3, 4, 5]
}
//打印對象數(shù)組的方法
public static void show(Num[] arrays) {
for (int i = 0; i < arrays.length; i++) {
System.out.print(arrays[i].getVal() + " ");
}
System.out.println();
}
class Num{
public int val = 0;
public Num(int val) {
this.val = val;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
}
拷貝引用類型
當數(shù)組中存放的元素為引用數(shù)據(jù)類型時,此時發(fā)生的是淺拷貝;
//1. for循環(huán)拷貝 (拷貝引用數(shù)據(jù)類型) ---淺拷貝
public static void main(String[] args) {
Num[] A = new Num[4];
A[0] = new Num(1);
A[1] = new Num(2);
A[2] = new Num(3);
A[3] = new Num(4);
Num[] B = new Num[4];
for (int i = 0; i < A.length; i++) {
B[i] = A[i];
}
show(A); //1 2 3 4
show(B); //1 2 3 4
System.out.println("===========修改后===========");
A[0].setVal(100);
show(A); //100 2 3 4
show(B); //100 2 3 4
}
2. copyof / copyOfRange
拷貝數(shù)值類型
當數(shù)組中存放的元素為基本數(shù)據(jù)類型時,此時發(fā)生的是深拷貝;
Arrays.copy(原數(shù)組,自定義新數(shù)組長度);
Arrays.copyOfRange(原數(shù)組,from,to);
注意拷貝截取的范圍是左閉右開的[from,to)
//2. copy / copyOfRange (拷貝數(shù)值類型) ---深拷貝
public static void main(String[] args) {
int[] A = {1,2,3,4,5};
int[] B = Arrays.copyOf(A,A.length);
int[] C = Arrays.copyOfRange(A,1,3);
System.out.println("A : " + Arrays.toString(A)); //A : [1, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [1, 2, 3, 4, 5]
System.out.println("C : " + Arrays.toString(C)); //C : [2, 3]
System.out.println("===========修改后===========");
A[0] = 100;
System.out.println("A : " + Arrays.toString(A)); //A : [100, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [1, 2, 3, 4, 5]
System.out.println("C : " + Arrays.toString(C)); //C : [2, 3]
}
拷貝引用類型
當數(shù)組中存放的元素為類的對象時,此時發(fā)生的是淺拷貝;
//2. copy / copyOfRange (拷貝引用類型) ---淺拷貝
public static void main(String[] args) {
Num[] A = new Num[4];
A[0] = new Num(1);
A[1] = new Num(2);
A[2] = new Num(3);
A[3] = new Num(4);
Num[] B = Arrays.copyOf(A,A.length);
show(A); //1 2 3 4
show(B); //1 2 3 4
System.out.println("===========修改后===========");
A[0].setVal(100);
show(A); //100 2 3 4
show(B); //100 2 3 4
}
class Num{
public int val = 0;
public Num(int val) {
this.val = val;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
}
3. arraycopy
拷貝數(shù)值類型
當數(shù)組中存放的元素為基本數(shù)據(jù)類型時,此時發(fā)生的是深拷貝;
System.arraycopy(src, srcPos dest, destPos, length);
其中各個參數(shù)分別表示 如下:
- src :源數(shù)組
- srcPos:源數(shù)組要復制的起始位置
- dest:目標數(shù)組
- destPos:目標數(shù)組復制的起始位置
- length:復制的長度
所以srcPos和destPos都為0,且length為源數(shù)組長度時,表示完完整整的拷貝過來了;那么截取范圍拷貝也舉個例子,下面的代碼中srcPos = 1,destPos = 2,length = 2,表示從A數(shù)組下標為1的位置開始截取2個元素,放到B數(shù)組中下標為2的位置作為起始位置,再對比一下輸出看看。
//3. arraycopy (拷貝數(shù)值類型) ---深拷貝
public static void main(String[] args) {
int[] A = {1,2,3,4,5};
int[] B = new int[A.length];
//System.arraycopy(A,0,B,0,A.length);
System.arraycopy(A,1,B,2,2);
System.out.println("A : " + Arrays.toString(A)); //A : [1, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [0, 0, 2, 3, 0]
System.out.println("===========修改后===========");
A[0] = 100;
System.out.println("A : " + Arrays.toString(A)); //A : [100, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [0, 0, 2, 3, 0]
}
拷貝引用類型
當數(shù)組中存放的元素為類的對象時,此時發(fā)生的是淺拷貝;
//3. arraycopy (拷貝引用類型) ---淺拷貝
public static void main(String[] args) {
Num[] A = new Num[4];
A[0] = new Num(1);
A[1] = new Num(2);
A[2] = new Num(3);
A[3] = new Num(4);
Num[] B = new Num[4];
System.arraycopy(A,0,B,0,A.length);
show(A); //1 2 3 4
show(B); //1 2 3 4
System.out.println("===========修改后===========");
A[0].setVal(100);
show(A); //100 2 3 4
show(B); //100 2 3 4
}
class Num{
public int val = 0;
public Num(int val) {
this.val = val;
}
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
}
4. clone
拷貝數(shù)值類型
當數(shù)組中存放的元素為基本數(shù)據(jù)類型時,此時發(fā)生的是深拷貝;
//4. clone (拷貝數(shù)值類型) ---深拷貝
public static void main(String[] args) {
int[] A = {1,2,3,4,5};
int[] B = A.clone();
System.out.println("A : " + Arrays.toString(A)); //A : [1, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [1, 2, 3, 4, 5]
System.out.println("===========修改后===========");
A[0] = 100;
System.out.println("A : " + Arrays.toString(A)); //A : [100, 2, 3, 4, 5]
System.out.println("B : " + Arrays.toString(B)); //B : [1, 2, 3, 4, 5]
}
拷貝引用類型
當數(shù)組中存放的元素為類的對象時,此時發(fā)生的是淺拷貝;
//4. clone (拷貝引用類型) ---淺拷貝
public static void main(String[] args) {
Num[] A = new Num[4];
A[0] = new Num(1);
A[1] = new Num(2);
A[2] = new Num(3);
A[3] = new Num(4);
Num[] B = A.clone();
show(A); //1 2 3 4
show(B); //1 2 3 4
System.out.println("===========修改后===========");
A[0].setVal(100);
show(A); //100 2 3 4
show(B); //100 2 3 4
}
5. 總結(jié)
| 拷貝方式 | 數(shù)值類型 | 引用類型 | 推薦使用 |
|---|---|---|---|
| for循環(huán) | 深拷貝 | 淺拷貝 | |
| copyof | 深拷貝 | 淺拷貝 | √ |
| arraycopy | 深拷貝 | 淺拷貝 | √ |
| clone | 深拷貝 | 淺拷貝 |
由于arraycopy底層是C++寫的,所以速度快,更多的是使用這個方法。
注意:本文中所有的引用數(shù)據(jù)類型都是以類的對象為例,使用的是對象數(shù)組,我們也知道引用類型包括類,接口,字符串等等。但是需要注意字符串是新的變量,所以如果是連個字符串數(shù)組進行拷貝,即使他們是引用類型,但是每次都會創(chuàng)建了一個字符串數(shù)組對象, 因此, 修改原數(shù)組, 不會影響到新數(shù)組,即深拷貝。
以上就是詳解Java數(shù)組的四種拷貝方式的詳細內(nèi)容,更多關(guān)于Java數(shù)組拷貝的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java客戶端Jedis操作Redis Sentinel 連接池的實現(xiàn)方法
下面小編就為大家?guī)硪黄猨ava客戶端Jedis操作Redis Sentinel 連接池的實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-03-03
java之scan.next()與scan.nextline()函數(shù)的使用及區(qū)別
這篇文章主要介紹了java之scan.next()與scan.nextline()函數(shù)的使用及區(qū)別,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04
詳解spring security之httpSecurity使用示例
這篇文章主要介紹了詳解spring security之httpSecurity使用示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
詳談Java中net.sf.json包關(guān)于JSON與對象互轉(zhuǎn)的坑
下面小編就為大家分享一篇Java中net.sf.json包關(guān)于JSON與對象互轉(zhuǎn)的坑,具有很好的參考價值,希望對大家有所幫助2017-12-12
JavaWeb項目實現(xiàn)文件上傳動態(tài)顯示進度實例
本篇文章主要介紹了JavaWeb項目實現(xiàn)文件上傳動態(tài)顯示進度實例,具有一定的參考價值,有興趣的可以了解一下。2017-04-04

