一、前言
对数组的复制,有四种方法:

for
clone
System.arraycopy
arrays.copyof
下面分析一下最常用的System.arraycopy()

二、源码拜读
1、源码

2、参数分析
Object src : 原数组
int srcPos : 从元数据的起始位置开始
Object dest : 目标数组
int destPos : 目标数组的开始起始位置
int length : 要copy的数组的长度
三、深拷贝与浅拷贝
如何区分深拷贝与浅拷贝,简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。

1、简单类型(深拷贝)
package com.guor.test.javaSE.collection;

import java.util.Arrays;

public class ArrayTest {

public static void main(String[] args) {getStringArrayFromObjectArray2();
}private static void copySelf() {int[] ids = { 1, 2, 3, 4, 5 };  System.out.println(Arrays.toString(ids));//System.arraycopy(src, srcPos, dest, destPos, length);// 把从索引0开始的2个数字复制到索引为3的位置上  System.arraycopy(ids, 0, ids, 3, 2);System.out.println(Arrays.toString(ids));//[1, 2, 3, 1, 2]
}private static void copyToOther() {int[] ids = { 1, 2, 3, 4, 5 };  //将数据的索引1开始的3个数据复制到目标的索引为0的位置上  int[] other = new int[5];System.arraycopy(ids, 1, other, 0, 3);System.out.println(Arrays.toString(ids));//[1, 2, 3, 4, 5]深复制System.out.println(Arrays.toString(other));//[2, 3, 4, 0, 0]
}//如果是类型转换问题,获取整形
private static void getIntegerArrayFromObjectArray() {Object[] obj1 = { 1, 2, 3, "4", "5" }; Integer[] obj2 = new Integer[5];try {System.arraycopy(obj1, 0, obj2, 0, obj1.length);} catch (Exception e) {System.out.println("transfer exception:"+e);}System.out.println(Arrays.toString(obj1));System.out.println(Arrays.toString(obj2));
}//获取Object数组中的字符串类型数据
private static void getStringArrayFromObjectArray1() {Object[] obj3 = { 1, 2, 3, "4", "5" }; String[] obj4 = new String[5];try {System.arraycopy(obj3, 2, obj4, 2, 3);} catch (Exception e) {//transfer exception:java.lang.ArrayStoreExceptionSystem.out.println("transfer exception:"+e);}System.out.println(Arrays.toString(obj3));//[null, null, null, null, null]System.out.println(Arrays.toString(obj4));
}//获取Object数组中的字符串类型数据
private static void getStringArrayFromObjectArray2() {Object[] obj3 = { 1, 2, 3, "4", "5" }; String[] obj4 = new String[5];try {System.arraycopy(obj3, 3, obj4, 3, 2);} catch (Exception e) {System.out.println("transfer exception:"+e);}System.out.println(Arrays.toString(obj3));//[null, null, null, 4, 5]System.out.println(Arrays.toString(obj4));obj3[3] = "zhangssan";System.out.println("查看是浅复制还是深复制~~~~~");System.out.println(Arrays.toString(obj3));System.out.println(Arrays.toString(obj4));
}

}
只有普通数据类型和String类型是深拷贝!

2、二维数组(浅拷贝)
//二维数组
public static void twoArray() {
int[] arr1 = {1, 2};
int[] arr2 = {3, 4};
int[] arr3 = {5, 6};

int[][] src = new int[][]{arr1, arr2, arr3};print("原始模样:", src);
int[][] dest = new int[3][];
System.arraycopy(src, 0, dest, 0, 3);System.out.println("改变前");
print("src = ", src);
print("dest = ", dest);//原数组改变后观察新数组是否改变,改变->浅复制,不改变->深复制
src[0][0] = -1;System.out.println("改变后");
print("src = ", src);
print("dest = ", dest);

}

//二维数组toString()
private static void print(String string, int[][] arr) {
System.out.print(string);
for (int[] a : arr) {
for (int i : a) {
System.out.print(i + " “);
}
System.out.print(”,");
}
System.out.println();
}
二维数组属于浅拷贝,原始数组改变后,复制的数据也发生了改变!

3、对象复制(深拷贝?)

四、System.arraycopy是不安全的
1、代码实例
多线程对数组进行复制,看System.arraycopy线程是否安全?

package com.guor.test.javaSE.collection;

import java.util.Arrays;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class ArrayTest2 {
private static int[] arrayOriginal = new int[1024 * 1024 * 10];
private static int[] arraySrc = new int[1024 * 1024 * 10];
private static int[] arrayDest = new int[1024 * 1024 * 10];
private static ReentrantLock lock = new ReentrantLock();

private static void modify() {for (int i = 0; i < arraySrc.length; i++) {arraySrc[i] = i + 1;}
}private static void copy() {System.arraycopy(arraySrc, 0, arrayDest, 0, arraySrc.length);
}private static void init() {for (int i = 0; i < arraySrc.length; i++) {arrayOriginal[i] = i;arraySrc[i] = i;arrayDest[i] = 0;}
}private static void doThreadSafeCheck() throws Exception {for (int i = 0; i < 100; i++) {System.out.println("run count: " + (i + 1));init();Condition condition = lock.newCondition();new Thread(new Runnable() {@Overridepublic void run() {lock.lock();condition.signalAll();lock.unlock();copy();}}).start();lock.lock();// 这里使用 Condition 来保证拷贝线程先已经运行了.condition.await();lock.unlock();Thread.sleep(2); // 休眠2毫秒, 确保拷贝操作已经执行了, 才执行修改操作.modify();// 如果 System.arraycopy 是线程安全的, 那么先执行拷贝操作, 再执行修改操作时, 不会影响复制结果, 因此 arrayOriginal 必然等于 arrayDist; if (!Arrays.equals(arrayOriginal, arrayDest)) {throw new RuntimeException("System.arraycopy is not thread safe");}}
}public static void main(String[] args) throws Exception {//doThreadSafeCheck();executeTime();
}private static void executeTime() {String[] srcArray = new String[1000000];String[] forArray = new String[srcArray.length];String[] arrayCopyArray  = new String[srcArray.length];//初始化数组for(int i  = 0 ; i  < srcArray.length ; i ++){srcArray[i] = String.valueOf(i);}long forStartTime = System.currentTimeMillis();for(int index  = 0 ; index  < srcArray.length ; index ++){forArray[index] = srcArray[index];}long forEndTime = System.currentTimeMillis();System.out.println("for方式复制数组:"  + (forEndTime - forStartTime));long arrayCopyStartTime = System.currentTimeMillis();System.arraycopy(srcArray,0,arrayCopyArray,0,srcArray.length);long arrayCopyEndTime = System.currentTimeMillis();System.out.println("System.arraycopy复制数组:"  + (arrayCopyEndTime - arrayCopyStartTime));
}

}
2、代码思路分析
arrayOriginal 和 arraySrc 初始化时是相同的, 而 arrayDist 是全为零的.

启动一个线程运行 copy() 方法来拷贝 arraySrc 到 arrayDist 中.

在主线程执行 modify() 操作, 修改 arraySrc 的内容. 为了确保 copy() 操作先于 modify() 操作, 我使用 Condition, 并且延时了两毫秒, 以此来保证执行拷贝操作(即System.arraycopy) 先于修改操作.

根据第三点, 如果 System.arraycopy 是线程安全的, 那么先执行拷贝操作, 再执行修改操作时, 不会影响复制结果, 因此 arrayOriginal 必然等于 arrayDist; 而如果 System.arraycopy 是线程不安全的, 那么 arrayOriginal 不等于 arrayDist.

3、控制台输出

————————————————
版权声明:本文为CSDN博主「GooReey」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/guorui_java/article/details/113187970

System.arraycopy详解相关推荐

  1. System.arraycopy()详解

    java.lang.System.arraycopy() 方法复制指定的源数组的数组 ,在被copy的数组指定的位置开始,到目标数组的指定位置. 具体方法如下: public static void ...

  2. byte数组快速拷贝,byte数组合并,System.arraycopy详解

    博客来源: 项目过程中用到byte[]数组相加问题,给出两个byte[] 需要合并成一个byte[]进行计算-那么需求来了--数据量达10W级,怎么合并 调用系统自带方法(System.arrayco ...

  3. System.load 和 System.loadLibrary详解

    System.load 和 System.loadLibrary详解 1.它们都可以用来装载库文件,不论是JNI库文件还是非JNI库文件.在任何本地方法被调用之前必须先用这个两个方法之一把相应的JNI ...

  4. system()函数详解

    windows下system () 函数详解 windows操作系统下system () 函数详解(主要是在C语言中的应用) 函数名: system 功 能: 发出一个DOS命令 用 法: int s ...

  5. java system sleep_详解Java中的sleep()和wait()的区别

    详解Java中的sleep()和wait()的区别 对于sleep()方法,我们首先要知道该方法是属于Thread类中的.而wait()方法,则是属于Object类中的. sleep()方法导致了程序 ...

  6. [system] systemd详解

    文章目录 systemd 由来 概述 查看版本号 兼容性 系统管理 systemctl 管理系统. systemd-analyze 查看启动耗时. hostnamectl 看当前主机的信息. loca ...

  7. 1.10 System类详解

    System 类位于 java.lang 包,代表当前 Java 程序的运行平台,系统级的很多属性和控制方法都放置在该类的内部.由于该类的构造方法是 private 的,所以无法创建该类的对象,也就是 ...

  8. Java System类详解

    System 类位于 java.lang 包,代表当前 Java 程序的运行平台,系统级的很多属性和控制方法都放置在该类的内部.由于该类的构造方法是 private 的,所以无法创建该类的对象,也就是 ...

  9. 三星root后进入android system recovery后,如何尝试使用ODIN去恢复启动界面是Android system recovery详解...

    刷机,是手机方面的专业术语,是指通过一定的方法更改或替换手机中原本存在的一些语言.图片.铃声.软件或者操作系统.通俗来讲,刷机就是给手机重装系统.刷机可以使手机的功能更加完善,并且可以使手机还原到原始 ...

最新文章

  1. 烂泥:net use与shutdown配合使用,本机重启远程服务器
  2. php根据数组某一字段排序,php如何根据数组中某一字段来实现排序
  3. 页面饼图不显示_教你烙饼的懒人做法,不沾手不揉面,比蛋糕还香,凉了更好吃...
  4. 使用Linux LiveCD 评估系统的安全性
  5. [转]一张图理解prototype、proto和constructor的三角关系
  6. 使用.NET Remoting开发分布式应用——基于租约的生存期(转载)
  7. 前端学习(2250)拉取代码文件
  8. Mac安装brew及报错处理办法
  9. MIP 技术交流分享(3月15日)
  10. oracle命中率sql,Oracle 检查命中率的SQL
  11. python 格式化输出
  12. Microsoft SQL Server 2005简体中文开发版下载说明
  13. 八,分隔符,其他符号和数据的讲解
  14. 1671. Anansi's Cobweb(并查集)
  15. Java导出Excel和Word
  16. MySQL管理员须知的两大漏洞与修复方法
  17. PAT乙级 1052 卖个萌 (0/20 分) Java 未实现
  18. call(zoom)_如何解决您的Zoom Call问题
  19. C++实现中文大写与阿拉伯数字的相互转换(类封装)
  20. jenkins+pipeline+Amazon_EKS部署java服务

热门文章

  1. memcached简单的使用教程
  2. asp.net findcontrol html控件,findcontrol-在ASP.NET中查找控件的更好方法
  3. Linux 5.10 LTS 发布,支持到 2026 年
  4. 开源项目的名称背后都有哪些故事?
  5. VS Code 的 python 扩展发布,绘图功能更强大
  6. mysql jdbc百度_mysql8.0 jdbc连接注意事项
  7. abaqus推荐用哪一版本的_ABAQUS推荐资料合集(一)
  8. azw3转换为pdf_干货:如何Java 将 Word 文档转换为 PDF
  9. python plot函数label_python – Matplotlib Contour Clabel位置
  10. c语言成绩管理系统不用结构体,不用指针链表和结构体数组怎么编学生成绩管理系统啊...