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