1.System.arraycopy常用于数组间的赋值,在复制数据量庞大时,优先采用这种方法,因为该方法是对内存的直接访问,少了for遍历的寻址时间,因此,时间复杂度低,其弊端为,它是线程不安全的,在使用多线程操作它时,会抛运行时异常,代码后续补充

  PS:数组对象复制的方法有:

  • for
  • clone
  • System.arraycopy
  • arrays.copyof
  • array.slice
  • array.concat
  • JSON.parse

2.在项目中一般用于自定义TCP协议的数据包解析,和数组的快速复制

3.复制分为深度复制和浅度复制,,System.arraycopy() 在拷贝 对象 数组的时候,采用的使用浅度复制,复制结果是一维的引用变量传递给副本的一维数组,修改副本时,会影响原来的数组。

这两种复制的区别:

          1.浅拷贝是指在拷贝对象时,对于基本数据类型的变量会重新复制一份,而对于引用类型的变量只是对引用地址进行拷贝,

           ***没有对引用指向的对象进行拷贝。

          2.而深拷贝是指在拷贝对象时,同时会对引用指向的对象进行拷贝。因此,操作新对象,不影响原对象

         ***可变对象向不变对象互相转换,

 总结:区别就在于是否对  对象中的引用变量所指向的对象进行拷贝。

 

4.一维数组和多维数组的复制的区别

String[] st  = {"A","B","C","D","E"};
        String[] dt  = new String[5];
        System.arraycopy(st, 0, dt, 0, 5);
        
        //改变dt的值
        dt[3] = "M";
        dt[4] = "V";
        
        System.out.println("两个数组地址是否相同:" + (st == dt)); //false
        
        for(String str : st){
            System.out.print(" " + str +" ");   // A  B  C  D  E 
            
        }
        System.out.println(); 
        for(String str : dt){
            System.out.print(" " + str +" ");   // A  B  C  M  V 
        }

使用该方法对一维数组在进行复制之后,目标数组修改不会影响原数据,这种复制属性值传递,修改副本不会影响原来的值。

特殊情况:

String[] st  = {"A","B","C","D","E"};
        String[] dt  = new String[5];
        System.arraycopy(st, 0, dt, 0, 5);

       for(String str : st){
            System.out.print(" " + str +" ");   // A  B  C  D  E 
            
        }
        System.out.println(); 
        for(String str : dt){
            System.out.print(" " + str +" ");   // A  B  C  D  E 
        }

        System.out.println("数组内对应位置的String地址是否相同:" + st[0] == dt[0]); // true

既然是属性值传递,为什么 st[0] == dt[0] 会相等呢? 我们再深入验证一下:

String[] st  = {"A","B","C","D","E"};
        String[] dt  = new String[5];
        System.arraycopy(st, 0, dt, 0, 5);
        dt[0] = "F" ;
        
        for(String str : st){
            System.out.print(" " + str +" ");   // A  B  C  D  E 
            
        }
        System.out.println(); 
        for(String str : dt){
            System.out.print(" " + str +" ");   // F  B  C  D  E 
        }


        System.out.println("数组内对应位置的String地址是否相同:" + st[0] == dt[0]); // false

通过以上两段代码可以推断,在System.arraycopy()进行复制的时候,首先检查了字符串常量池是否存在该字面量,一旦存在,则直接返回对应的内存地址,如不存在,则在内存中开辟空间保存对应的对象。

代码:二维数组的复制

String[][] s1 = {
                    {"A1","B1","C1","D1","E1"},
                    {"A2","B2","C2","D2","E2"},
                    {"A3","B3","C3","D3","E3"}
                        };
        String[][] s2 = new String[s1.length][s1[0].length];  
        
        System.arraycopy(s1, 0, s2, 0, s2.length);  
        
        for(int i = 0;i < s1.length ;i++){ 
         
           for(int j = 0; j< s1[0].length ;j++){  
              System.out.print(" " + s1[i][j] + " ");
           }  
           System.out.println();  
        }  
        
        //  A1  B1  C1  D1  E1 
        //  A2  B2  C2  D2  E2 
        //  A3  B3  C3  D3  E3 
        
        
        s2[0][0] = "V";
        s2[0][1] = "X";
        s2[0][2] = "Y";
        s2[0][3] = "Z";
        s2[0][4] = "U";
        
        System.out.println("----修改值后----");  
        
        
        for(int i = 0;i < s1.length ;i++){  
               for(int j = 0; j< s1[0].length ;j++){  
                  System.out.print(" " + s1[i][j] + " ");
               }  
               System.out.println();  
         }  

        //  Z   Y   X   Z   U 
        //  A2  B2  C2  D2  E2 
        //  A3  B3  C3  D3  E3

上述代码是对二维数组进行复制,数组的第一维装的是一个一维数组的引用,第二维里是元素数值。对二维数组进行复制后后,第一维的引用被复制给新数组的第一维,也就是两个数组的第一维都指向相同的“那些数组”。而这时改变其中任何一个数组的元素的值,其实都修改了“那些数组”的元素的值,所以原数组和新数组的元素值都一样了。