System.arraycopy详解
一、前言
对数组的复制,有四种方法:
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详解相关推荐
- System.arraycopy()详解
java.lang.System.arraycopy() 方法复制指定的源数组的数组 ,在被copy的数组指定的位置开始,到目标数组的指定位置. 具体方法如下: public static void ...
- byte数组快速拷贝,byte数组合并,System.arraycopy详解
博客来源: 项目过程中用到byte[]数组相加问题,给出两个byte[] 需要合并成一个byte[]进行计算-那么需求来了--数据量达10W级,怎么合并 调用系统自带方法(System.arrayco ...
- System.load 和 System.loadLibrary详解
System.load 和 System.loadLibrary详解 1.它们都可以用来装载库文件,不论是JNI库文件还是非JNI库文件.在任何本地方法被调用之前必须先用这个两个方法之一把相应的JNI ...
- system()函数详解
windows下system () 函数详解 windows操作系统下system () 函数详解(主要是在C语言中的应用) 函数名: system 功 能: 发出一个DOS命令 用 法: int s ...
- java system sleep_详解Java中的sleep()和wait()的区别
详解Java中的sleep()和wait()的区别 对于sleep()方法,我们首先要知道该方法是属于Thread类中的.而wait()方法,则是属于Object类中的. sleep()方法导致了程序 ...
- [system] systemd详解
文章目录 systemd 由来 概述 查看版本号 兼容性 系统管理 systemctl 管理系统. systemd-analyze 查看启动耗时. hostnamectl 看当前主机的信息. loca ...
- 1.10 System类详解
System 类位于 java.lang 包,代表当前 Java 程序的运行平台,系统级的很多属性和控制方法都放置在该类的内部.由于该类的构造方法是 private 的,所以无法创建该类的对象,也就是 ...
- Java System类详解
System 类位于 java.lang 包,代表当前 Java 程序的运行平台,系统级的很多属性和控制方法都放置在该类的内部.由于该类的构造方法是 private 的,所以无法创建该类的对象,也就是 ...
- 三星root后进入android system recovery后,如何尝试使用ODIN去恢复启动界面是Android system recovery详解...
刷机,是手机方面的专业术语,是指通过一定的方法更改或替换手机中原本存在的一些语言.图片.铃声.软件或者操作系统.通俗来讲,刷机就是给手机重装系统.刷机可以使手机的功能更加完善,并且可以使手机还原到原始 ...
最新文章
- 烂泥:net use与shutdown配合使用,本机重启远程服务器
- php根据数组某一字段排序,php如何根据数组中某一字段来实现排序
- 页面饼图不显示_教你烙饼的懒人做法,不沾手不揉面,比蛋糕还香,凉了更好吃...
- 使用Linux LiveCD 评估系统的安全性
- [转]一张图理解prototype、proto和constructor的三角关系
- 使用.NET Remoting开发分布式应用——基于租约的生存期(转载)
- 前端学习(2250)拉取代码文件
- Mac安装brew及报错处理办法
- MIP 技术交流分享(3月15日)
- oracle命中率sql,Oracle 检查命中率的SQL
- python 格式化输出
- Microsoft SQL Server 2005简体中文开发版下载说明
- 八,分隔符,其他符号和数据的讲解
- 1671. Anansi's Cobweb(并查集)
- Java导出Excel和Word
- MySQL管理员须知的两大漏洞与修复方法
- PAT乙级 1052 卖个萌 (0/20 分) Java 未实现
- call(zoom)_如何解决您的Zoom Call问题
- C++实现中文大写与阿拉伯数字的相互转换(类封装)
- jenkins+pipeline+Amazon_EKS部署java服务
热门文章
- memcached简单的使用教程
- asp.net findcontrol html控件,findcontrol-在ASP.NET中查找控件的更好方法
- Linux 5.10 LTS 发布,支持到 2026 年
- 开源项目的名称背后都有哪些故事?
- VS Code 的 python 扩展发布,绘图功能更强大
- mysql jdbc百度_mysql8.0 jdbc连接注意事项
- abaqus推荐用哪一版本的_ABAQUS推荐资料合集(一)
- azw3转换为pdf_干货:如何Java 将 Word 文档转换为 PDF
- python plot函数label_python – Matplotlib Contour Clabel位置
- c语言成绩管理系统不用结构体,不用指针链表和结构体数组怎么编学生成绩管理系统啊...