当前位置: 首页 > news >正文

深入解析Java中的数组复制:System.arraycopy、Arrays.copyOf和Arrays.copyOfRange

当涉及到在Java中处理数组时,有许多方法可供选择,其中一些包括System.arraycopy()Arrays.copyOf()Arrays.copyOfRange()。这些方法允许您在不同的数组之间复制数据,但它们之间有一些细微的差异。在本篇博客文章中,我们将深入探讨这些方法,以便您了解何时使用它们以及如何正确使用它们。

System.arraycopy()

System.arraycopy方法是Java中的本地方法,其实际实现是由Java虚拟机的底层实现提供的。

public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);

参数说明:

  • src:源数组
  • srcPos:源数组中的起始位置
  • dest:目标数组
  • destPos:目标数组中的起始位置
  • length:要复制的元素个数

System.arraycopy()方法的性能非常高,因为它是由底层代码实现的,并且能够利用硬件的特性来进行快速的数据复制。它通常比使用循环逐个复制数组元素要快得多。

System.arraycopy() 可以用于向上或向下转型,但在使用时要谨慎,确保数据类型兼容性和运行时类型检查。如果数据类型不匹配,虽然可通过编译,但运行时会跑出运行时异常java.lang.ArrayStoreException。最好的做法是尽量避免不必要的类型转换,以保持代码的清晰性和可维护性。

示例:

public static void main(String[] args) {String[] strArray = new String[]{"xj1","xj2","xj3","xj4","xj5"};String[] strArrayCopy = new String[5];System.arraycopy(strArray,0,strArrayCopy,0,3);//向下转型TestEntity[] testArray = new TestChildEntity[]{new TestChildEntity("xiuji","xj")} ;TestChildEntity[] testChildArrayCopy = new TestChildEntity[2];System.arraycopy(testArray,0,testChildArrayCopy,0,1);System.out.println(Arrays.toString(strArrayCopy));System.out.println(Arrays.toString(testChildArrayCopy));
}

运行结果

[xj1, xj2, xj3, null, null]
[TestChildEntity{nickName='xj'name='xiuji'}, null]

Arrays.copyOf()

语法:

不转换类型

copyOf(T[] original, int newLength)

转换类型

copyOf(U[] original, int newLength, Class<? extends T[]> newType)

参数说明:

  • original:要复制的原始数组。
  • newLength:新数组的长度,它可以比原始数组的长度长或短。
  • newType:新数组的类型,是一个Class对象,通常是一个数组类。它用于确定新数组的类型。

源码:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);这是一个三元条件运算符,System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength));return copy;
}
  • @SuppressWarnings("unchecked"):这个注解,用于告诉编译器忽略未经检查的转换警告。因为在这个方法中进行了类型转换,所以使用这个注解来抑制警告。

  • T[] copy = ((Object)newType == (Object)Object[].class): 这个三元条件运算符,它根据newType的类型创建一个新的数组copy。如果newType是Object[].class,则创建一个Object类型的新数组;否则,使用Array.newInstance()方法创建一个新数组,其类型由newType的组件类型确定。

  • System.arraycopy(original, 0, copy, 0,Math.min(original.length, newLength)): System.arraycopy()方法用于将原始数组的元素复制到新数组中。它的参数包括原始数组、原始数组的起始位置(0表示从第一个元素开始)、目标数组(即新数组)、目标数组的起始位置(0表示从第一个位置开始复制),以及要复制的元素数量,数量由原始数组长度和newLength中较小的那个确定。

示例:

public static void main(String[] args) {String[] strArray = new String[]{"xj1","xj2","xj3","xj4","xj5"};String[] strArrayCopy = Arrays.copyOf(strArray,8);//向下转型TestEntity[] testArray = new TestChildEntity[]{new TestChildEntity("xiuji","xj")} ;TestChildEntity[] testChildArrayCopy =Arrays.copyOf(testArray,3,TestChildEntity[].class);System.out.println(Arrays.toString(strArrayCopy));System.out.println(Arrays.toString(testChildArrayCopy));}

运行结果:

[xj1, xj2, xj3, xj4, xj5, null, null, null]
[TestChildEntity{nickName='xj'name='xiuji'}, null, null]

Arrays.copyOfRange()

语法:

不转换类型

copyOfRange(U[] original, int from, int toe) 

转换类型

copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) 
  • original:这是要复制元素的原始数组。
  • from:这是要复制的范围的起始索引。
  • to:这是要复制的范围的结束索引(不包括在内)。
  • newType:这是新数组的类型,通常是一个数组类。

源码:

public static <T,U> T[] copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {int newLength = to - from;if (newLength < 0)throw new IllegalArgumentException(from + " > " + to);@SuppressWarnings("unchecked")T[] copy = ((Object)newType == (Object)Object[].class)? (T[]) new Object[newLength]: (T[]) Array.newInstance(newType.getComponentType(), newLength);System.arraycopy(original, from, copy, 0,Math.min(original.length - from, newLength));return copy;
}
  • int newLength = to - from;:此行计算新数组的长度,基于指定的from和to索引。

  • if (newLength < 0) throw new IllegalArgumentException(from + " > " + to);:此行检查newLength是否为负数(即from是否大于to)。如果满足此条件,它将抛出IllegalArgumentException,指示from索引大于to索引。

  • @SuppressWarnings("unchecked"):此注解用于抑制未检查的类型转换警告。

  • T[] copy = ((Object)newType == (Object)Object[].class) ? (T[]) new Object[newLength] : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    此行根据指定的newType创建一个新数组copy。它使用反射来创建所需类型的数组。
    如果newType等于Object[].class,则创建一个新的Object数组,其长度为newLength。
    否则,它使用Array.newInstance创建一个新的数组,该数组的组件类型与newType的组件类型相同,长度为newLength。这使您能够创建特定类型的数组。

  • System.arraycopy(original, from, copy, 0, Math.min(original.length - from, newLength));
    此行使用System.arraycopy执行实际的数组复制操作。它将元素从original数组的from索引开始复制到copy数组的0索引开始的位置。要复制的元素数量由Math.min(original.length - from, newLength)确定,确保仅复制指定的范围。

示例:

public static void main(String[] args) {String[] strArray = new String[]{"xj1","xj2","xj3","xj4","xj5"};String[] strArrayCopy = Arrays.copyOfRange(strArray,2,4);//向下转型TestEntity[] testArray = new TestChildEntity[]{new TestChildEntity("xiuji","xj")} ;TestChildEntity[] testChildArrayCopy =Arrays.copyOfRange(testArray,0,1,TestChildEntity[].class);System.out.println(Arrays.toString(strArrayCopy));System.out.println(Arrays.toString(testChildArrayCopy));}

运行结果:

[xj3, xj4]
[TestChildEntity{nickName='xj'name='xiuji'}]

注意事项

在使用数组复制时,需要注意以下几点:

  • 如果新数组的长度小于源数组的长度,那么新数组将截取源数组的前几个元素。

  • 如果源数组中的元素是对象引用,那么新数组中的元素将仍然引用相同的对象,这意味着对新数组的修改可能会影响到源数组。

  • 如果源数组包含基本数据类型(如int、char等),新数组将包含这些基本数据类型的默认值,如0或’\0’

总结

在处理数组时,选择合适的复制方法取决于您的具体需求。以下是一些使用这些方法的一些建议:

  • 如果您需要高效的底层复制操作,并且能够手动计算起始位置和元素数量,那么System.arraycopy可能是一个不错的选择。
  • 如果您想要创建一个新数组,其长度与源数组相同,并且将源数组的内容全部复制到新数组中,那么Arrays.copyOf是一个方便的选择。
  • 如果您需要复制源数组的一部分内容到一个新数组中,那么Arrays.copyOfRange是最适合的。

不管您选择哪种方法,都可以确保在处理数组时能够更加灵活、高效和安全地进行操作。希望本文能够帮助您更好地理解和使用这些数组复制方法。

相关文章:

深入解析Java中的数组复制:System.arraycopy、Arrays.copyOf和Arrays.copyOfRange

当涉及到在Java中处理数组时&#xff0c;有许多方法可供选择&#xff0c;其中一些包括System.arraycopy()、Arrays.copyOf()和Arrays.copyOfRange()。这些方法允许您在不同的数组之间复制数据&#xff0c;但它们之间有一些细微的差异。在本篇博客文章中&#xff0c;我们将深入探…...

libc和glibc有什么区别

libc&#xff08;C Library&#xff09;是一个常见的术语&#xff0c;指的是C语言的标准函数库&#xff0c;提供了许多函数和常量供C语言程序使用。在不同的操作系统中&#xff0c;libc可能是不同的&#xff0c;但是它们都实现了C语言的标准库函数。 glibc&#xff08;GNU C L…...

基于SSM的在线云音乐系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…...

构建高效的BFF(Backend for Frontend):优化前端与后端协作

面试题分享 2023最新面试合集链接 2023大厂面试题PDF 面试题PDF版本 java、python面试题 项目实战:AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 史上最全文档AI绘画stab…...

喜报 | 实力亮相2023服贸会,擎创科技斩获领军人物奖创新案例奖

近日&#xff0c;由中华人民共和国商务部、北京市人民政府共同主办的中国&#xff08;北京&#xff09;国际服务贸易交易会&#xff08;简称服贸会)已圆满落幕。 本次会议中&#xff0c;发布了2023年度“数智影响力”征集活动获奖名单&#xff0c;擎创科技创始人兼CEO杨辰获企…...

科技革新自动驾驶:拓世AI智能助理携手跟您一起点亮未来之旅

科技改变生活&#xff0c;智能改变世界&#xff0c;近年来&#xff0c;随着科技的不断进步&#xff0c;政策和市场的赋能推动&#xff0c;自动驾驶已经成为当今社会最炙手可热的话题之一。从其中的技术发展趋势来看&#xff0c;我国自动驾驶模式正由单车智能向车路协同时代演进…...

【HCIE】01.IGP高级特性

高级特性&#xff1a;一条命令解决一个问题 OSPF快速收敛机制 发生故障重新计算拓扑的过程叫做收敛&#xff0c;设备现在本身就是PRC算法和I-SPF算法 PRC&#xff08;针对叶子节点&#xff0c;叶子代表路由&#xff09; 不需要命令配置&#xff0c;就是ospf的特性&#xff…...

知识大杂烩(uniapp)

首先声明&#xff1a;不敢保证都管用&#xff0c;这是我自己实践得来的。 box-shadow: 这段 CSS 样式代码用于创建一个阴影效果&#xff0c;它是通过 box-shadow 属性来实现的。让我解释一下这段代码的含义&#xff1a; - box-shadow: 这是 CSS 的属性&#xff0c;用于添加阴影…...

Jmeter压测监控体系搭建Docker+Influxdb+Grafana

章节目录&#xff1a; 一、背景介绍1.1 概述1.2 拓扑图 二、云服务器设置三、Docker3.1 概述3.2 搭建流程3.3 安装验证3.4 配置docker镜像加速3.5 取消sudo运行(可选操作) 四、InfluxDB4.1 镜像拉取4.2 运行数据库4.3 创建存储 jmeter 数据的库 五、Grafana5.1 镜像拉取5.2 关联…...

TDesign 点击高亮显示=》点击切换class类名

1. wx:for遍历数组 2. 在一行显示 2. 点击高亮...

容器编排学习(二)镜像制作和私有仓库介绍

一 Dockerfile 1 概述 commit的局限 很容易制作简单的镜像&#xff0c;但碰到复杂的情况就十分不方便例如碰到下面的情况需要设置默认的启动命令需要设置环境变量需要指定镜像开放某些特定的端口 Dockerfile就是解决这些问题的方法 Dockerfile是一种更强大的镜像制作方式…...

tcp记录

网络传输&#xff1a;大小端 Qt网络编程实现TCP通信 TCP/IP通讯与socket编程 Qt一步步搭建TcpServer1——封装QTcpServer&#xff0c;QTcpSocket qtcpserver官方文档 Python address already in use 服务器端的端口号和客户端的端口号没有关系 一般服务器是需要BIND指定端口号…...

IDEA中使用Java连接MySQL数据库的配置和使用方法

文章目录 IDE和必要配置数据库连接代码 IDE和必要配置 IDE&#xff1a;IntelliJ IDEA 2023.1 必要配置&#xff1a; 1、安装好JDK&#xff0c;并且配置环境变量 2、导入MYSQL数据库所需的驱动 如果没有导入&#xff0c;可以参考这篇文章IDEA中的MySQL数据库所需驱动包的下载和…...

android——服务JobService

JobService是Android L时候官方新增的组件&#xff0c;适用于需要特定条件才执行后台任务的场景。由系统统一管理和调度&#xff0c;在特定场景下使用JobService更加灵活和省心&#xff0c;相当于是Service的加强或者优化。 JobService是JobScheduler的回调&#xff0c;是安排的…...

一文讲清楚redis的线程池jedis

背景 在shigen实习的时候&#xff0c;遇到了日志系统的性能优化问题&#xff0c;当时的优化点就是&#xff1a;使用redis的线程池&#xff0c;实现并发状态下的性能优化。但是找了很多的技术方案&#xff0c;发现redis的线程池配置起来比较麻烦。正巧&#xff0c;这个周末shig…...

备战面试每日一题

1.如何理解this&#xff1f; this表示的是函数运行时自动生成的一个内部对象&#xff0c;只能在函数内部使用&#xff0c;总是指向调用它的对象。 this是在运行时进行绑定的&#xff0c;并不是在编写的时候绑定&#xff0c;它的上下文取决于函数调用时的各种条件。this的绑定…...

【嵌入式数据库之sqlite3】

目录 一.数据库基本概念&#xff08;理解&#xff09; 1.数据 2.数据库 二.常用的数据的数据库&#xff08;了解&#xff09; 1.大型数据库 2.中型数据库 3.小型数据库 三.基于嵌入式的数据库&#xff08;了解&#xff09; 四.SQLite基础&#xff08;了解&#xff09;…...

Android 9.0 pms中关于启动app时获取app的ActivityInfo信息相关源码分析

1.前言 在android9.0的系统rom定制化开发中,在对于app启动时,在进行系统中,通过Launcher调用pms来查询app的相关ActivityInfo的相关信息,然后调用 ams来启动activity,这篇来分析pms中获取app的ActivityInfo的相关信息的相关源码分析 2.pms中关于启动app时获取app的Activ…...

华为数通方向HCIP-DataCom H12-821题库(单选题:321-340)

第321题 BGP的Open报文是用于建立对等体连接的,以下哪一项不属于Open报文中携带的参数信息? A、发送者的Router ID B、AS号 C、BGP版本号 D、TCP端口号 答案:D 解析:以下是BGP的Open报文: 第322题 在建立BGP对等体的过程中,OpenSent状态表明BGP等待的Open报文 并对收…...

《TCP/IP网络编程》阅读笔记--基于TCP的服务器端/客户端

目录 1--TCP/IP协议栈 2--TCP服务器端默认函数调用顺序 3--TCP客户端的默认函数调用顺序 4--Linux实现迭代回声服务器端/客户端 5--Windows实现迭代回声服务器端/客户端 6--TCP原理 7--Windows实现计算器服务器端/客户端 1--TCP/IP协议栈 TCP/IP协议栈共分 4 层&#xf…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器

——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的​​一体化测试平台​​&#xff0c;覆盖应用全生命周期测试需求&#xff0c;主要提供五大核心能力&#xff1a; ​​测试类型​​​​检测目标​​​​关键指标​​功能体验基…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

go 里面的指针

指针 在 Go 中&#xff0c;指针&#xff08;pointer&#xff09;是一个变量的内存地址&#xff0c;就像 C 语言那样&#xff1a; a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10&#xff0c;通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...

算术操作符与类型转换:从基础到精通

目录 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 算术操作符超级详解 算术操作符&#xff1a;、-、*、/、% 赋值操作符&#xff1a;和复合赋值 单⽬操作符&#xff1a;、--、、- 前言&#xff1a;从基础到实践——探索运算符与类型转换的奥秘 在先前的文…...