好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

详解Java数组的四种拷贝方式

深拷贝与浅拷贝的区别

假设现在有原数组A以及拷贝后的数组B,若是改变A中的某一个值,B数组随之相应的发生变化的拷贝方式称为浅拷贝,反之B数组不受影响,则称为深拷贝;
简单总结一下两者的概念:

深拷贝:拷贝后,修改原数组,不会影响到新数组;

浅拷贝:拷贝后,修改原数组,新数组也会相应的发生改变;

1. for循环进行拷贝

拷贝数值类型

当数组中存放的元素为基本数据类型时,此时发生的是深拷贝;

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

//1. for循环拷贝  (拷贝数值类型) ---深拷贝

     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]

     }

     //打印对象数组的方法

     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;

     }

}

拷贝引用类型

当数组中存放的元素为引用数据类型时,此时发生的是浅拷贝;

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

//1. for循环拷贝  (拷贝引用数据类型) ---浅拷贝

     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

拷贝数值类型

当数组中存放的元素为基本数据类型时,此时发生的是深拷贝;

Arrays.copy(原数组,自定义新数组长度);

Arrays.copyOfRange(原数组,from,to);

注意拷贝截取的范围是左闭右开的[from,to)

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

//2. copy / copyOfRange  (拷贝数值类型) ---深拷贝

     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]

     }

拷贝引用类型

当数组中存放的元素为类的对象时,此时发生的是浅拷贝;

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

//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

拷贝数值类型

当数组中存放的元素为基本数据类型时,此时发生的是深拷贝;

System.arraycopy(src, srcPos dest, destPos, length);

其中各个参数分别表示 如下:

src :源数组 srcPos:源数组要复制的起始位置 dest:目标数组 destPos:目标数组复制的起始位置 length:复制的长度

所以srcPos和destPos都为0,且length为源数组长度时,表示完完整整的拷贝过来了;那么截取范围拷贝也举个例子,下面的代码中srcPos = 1,destPos = 2,length = 2,表示从A数组下标为1的位置开始截取2个元素,放到B数组中下标为2的位置作为起始位置,再对比一下输出看看。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

//3. arraycopy  (拷贝数值类型) ---深拷贝

     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]

     }

拷贝引用类型

当数组中存放的元素为类的对象时,此时发生的是浅拷贝;

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

//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

拷贝数值类型

当数组中存放的元素为基本数据类型时,此时发生的是深拷贝;

?

1

2

3

4

5

6

7

8

9

10

11

//4. clone  (拷贝数值类型) ---深拷贝

     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]

     }

拷贝引用类型

当数组中存放的元素为类的对象时,此时发生的是浅拷贝;

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

//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. 总结

拷贝方式 数值类型 引用类型 推荐使用
for循环 深拷贝 浅拷贝  
copyof 深拷贝 浅拷贝
arraycopy 深拷贝 浅拷贝
clone 深拷贝 浅拷贝  

由于arraycopy底层是C++写的,所以速度快,更多的是使用这个方法。

注意:本文中所有的引用数据类型都是以类的对象为例,使用的是对象数组,我们也知道引用类型包括类,接口,字符串等等。但是需要注意字符串是新的变量,所以如果是连个字符串数组进行拷贝,即使他们是引用类型,但是每次都会创建了一个字符串数组对象, 因此, 修改原数组, 不会影响到新数组,即深拷贝。

以上就是详解Java数组的四种拷贝方式的详细内容,更多关于Java数组拷贝的资料请关注其它相关文章!

原文链接:https://blog.csdn.net/Emperor10/article/details/121441247

查看更多关于详解Java数组的四种拷贝方式的详细内容...

  阅读:21次