Java通过底层原码了解数组拷贝
作者:白朝槿kk 发布时间:2021-10-07 12:47:47
循环对数组进行拷贝
利用循环对数组进行拷贝很简单,就是利用循环将要拷贝的数组的元素逐个赋值给新的数组。具体代码实现如下:
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] copy = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
copy[i] = arr[i];
}
}
这是我们一般会想到的方法,下面将一些JAVA为我们提供的一些比较方便的方法。
Arrays.copyOf方法
因为我是拷贝的整型数组,所以我用的就是拷贝整型数组的Arrays.copyOf方法。也可以拷贝其它类型的数组,并不是只能拷贝整型数组。
下面就以拷贝整型数组来讲解Arrays.copyOf方法,我们先来看一下Arrays.copyOf方法底层的原码:
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
我们可以看到Array.copyOf方法的返回值是是一个整型数组,而形参是有两个参数,一个是整型数组,另外一个是一个整型的变量。
形参中整型数组就是我们要拷贝数组的数组名
形参中的整型变量就是我们要拷贝数组的长度
因为是有返回值的,所以我们在使用Arrays.copyOf方法的时候,要有数组来接收返回值。代码实现如下:
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] copy =Arrays.copyOf(arr,arr.length);
}
注意:拷贝的长度是可以超过要拷贝数组的长度的,如果超过了拷贝数组的长度的话,那么多出来的元素值就为0;比如:我要拷贝arr数组,但是arr数组的大小为5,如果我在拷贝的时候,将arr.length*2了,那么copy这个数组大小就是变成10,并且6~10个元素值为0.这也算是扩容。
Arrays.copyofRange方法
如果我们要拷贝部分数组的一部分,就可以使用Arrays.copyRange这个方法。同上一样,也是用拷贝整型数组进行讲解,我们先看一下它底层的原码:
public static int[] copyOfRange(int[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
int[] copy = new int[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
我们通过Arrays.copyRange的原码可以看到返回值是一个整型的数组,而形参是一个整型数组,两个整型的变量。
形参中的整型数组就是要拷贝的数组的数组名
形参中的两个整型变量from和to就是你要拷贝数组元素的范围,注意这个范围是[form,to)是左闭右开的,不包括to那个位置的元素。代码实现如下:
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] copy = Arrays.copyOfRange(arr,1,3);
}
注意:数组下标是从0开始的,1~3号的元素是指2,3,4.但是右边是开区间,所以不包括4,因此copy这个数组知识拷贝了2和3这两个元素。
System.arraycopy方法
然后我们来讲一下System.arraycopy方法,其实细心的同学已经发现了,在前面两个方法的原码中都有System.arraycopy方法,他们的底层也是靠System.arraycopy方法来实现的。我们来先看一下它底层的原码
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
System.arraycopy是看不到实现的原码的,原因在于native,它的底层是C/C++来实现的。但是native方法的优点就是执行速度非常快。代码实现如下:
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] copy = new int[arr.length];
System.arraycopy(arr,0,copy,0,arr.length);
}
此时拷贝的是arr整个数组,如果想要部分拷贝,可以通过改变形参来完成部分拷贝
clone方法
最后一个是数组名.clone这个方法,这个方法了解即可,代码实现如下:
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
int[] copy = arr.clone();
}
这样就拷贝完了,这种方法主要是产生了对象的一个副本,地址还是不一样的。
来源:https://blog.csdn.net/m0_63463510/article/details/125657315


猜你喜欢
- 一、序言Java多线程编程线程池被广泛使用,甚至成为了标配。线程池本质是池化技术的应用,和连接池类似,创建连接与关闭连接属于耗时操作,创建线
- MyBatis的注解实现复杂映射开发实现复杂关系映射之前我们可以在映射文件中通过配置来实现,使用注解开发后,我们可以使用@Results注解
- 今天介绍一个自己做的快递单号查询的简单APP,供大家参考。由于需要使用http和json,本文在build.gradle(module:ap
- 示例 1 :使用搜索表单创建全屏模式我们要构建的小应用程序有一个应用程序栏,右侧有一个搜索按钮。按下此按钮时,将出现一个全屏模式对话框。它不
- IDEA自定义pom依赖抽离公共代码,代码解耦,减少重复第一步: 抽离公共部分的代码第二步: 点击右侧工具栏的maven,刷新,点击skip
- 前言: 有时候我们需要实现长按选择文字功能,比如阅读器一般都有这个功能,有时候某个自定义控件上可能就有这种需求,如何实现呢?正好最近还算闲,
- 可以使用 graphics2D 类提供的 shear(
- 在上一篇实现了简单的画板功能, 这篇实现橡皮擦功能,首先分析一下应该如何实现,在Andriod有个图像混合(Xfermode)概念,利用这个
- 1.如图所示,Spring配置文件应该带有是树叶标识,但此处显示的为普通的properties文件2.选择Open Module Setti
- 在android智能平板设备应用中,一项耗时的操作总要有个提示进度的框来提高用户的操作体验,操作进度提示框就显得很常用了。系统自带的有进度条
- 使用简单的fragment实现左侧导航,供大家参考,具体内容如下先上效果图:MainActivity.javapublic class Ma
- 前言记得几年前有一次栈长去面试,问到了这么一个问题:Java中的对象都是在堆中分配吗?说明为什么!当时我被问得一脸蒙逼,瞬间被秒杀得体无完肤
- Ctrl+1 快速修复Ctrl+D: 删除当前行 Ctrl+Alt+↓ 复制当前行到下一行(复制增加)Ctrl+Alt+↑ 复制当
- 正在编译...1>Ipv4IPv6traceroutesrc.cpp1>d:\研究生\c++\study\test\test\i
- 项目需求,一直用eclipse的我,也要改用IDEA了,一开始,很不习惯。经过几天的慢慢摸索和习惯之后,发现IDEA确实很好用。dark的界
- 前言说起网络爬虫,大家想起的估计都是 Python ,诚然爬虫已经是 Python 的代名词之一,相比 Java 来说就要逊色不少。有不少人
- 简介本文介绍Idea如何根据maven依赖名查找它是哪个pom.xml引入的。有时候会有这样的问题:我们知道项目里用了某个依赖,想知道它是项
- Activity栈主要用于管理Activity的切换。当使用Intent跳转至某个目标Activity,需要根据目标Activity的加载模
- 一、前言Java 8 引入了默认方法以及可以在接口中定义的静态方法。默认方法是一个普通的 java 方法,但以 default 关键字开头,
- (1)很多朋友在使用genymotion开发安卓应用程序的时候,会遇见完全正确的安装但是在运行的时候仍然找不到,genymotion上的设备