Java复制数组的方法
java数组拷贝主要有四种方法,分别是循环赋值,System.arraycopy(),Arrays.copyOf()(或者Arrays.copyOfRange)和clone()方法。下面分别介绍一下这几种拷贝。
一、循环拷贝(速度相对比较慢)
循环拷贝其实没什么好说的啦,就是用一个for循环进行元素的逐个拷贝,进行深拷贝或者浅复制这个大家可以自己把握。
二、System.arraycopy(浅拷贝)
这个是系统提供的拷贝方式,也是我们推荐使用的拷贝方式,它是浅拷贝,也就是说对于非基本类型而言,它拷贝的是对象的引用,而不是去新建一个新的对象。通过它的代码我们可以看到,这个方法不是用java语言写的,而是底层用c或者c++实现的,因而速度会比较快。
1 public static native void arraycopy
2 (Object src, int srcPos,Object dest, int destPos,int length);
通过源代码我们可以看到,关键字native说明它不是用java语言写的,而是调用其他语言的代码。
1、先来看看基本数据类型的System.arraycopy() 方法拷贝:
1 import java.util.Arrays;
2 public class TestDemo {
3 public static void main(String[] args) {
4
5 int[] array1 = new int[]{1,2,8,7,6};
6 int[] array2 = new int[array1.length];
7 System.arraycopy(array1, 0, array2, 0, array1.length);
8
9 System.out.println("array1 = " + Arrays.toString(array1));
10 System.out.println("array2 = " + Arrays.toString(array2));
11 System.out.println("=========================");
12
13 array2[0] = 100;
14 System.out.println("array1 = " + Arrays.toString(array1));
15 System.out.println("array2 = " + Arrays.toString(array2));
16
17 }
18 }
这段程序的结果是:
array1 = [1, 2, 8, 7, 6]
array2 = [1, 2, 8, 7, 6]
=========================
array1 = [1, 2, 8, 7, 6]
array2 = [100, 2, 8, 7, 6]
由结果可以看出,当对复制数组的某个元素进行改变时,并不影响被复制数组对应元素,即对于基本数据类型来说System.arraycopy() 方法是深拷贝。
2、同样的,看一下当对象不是基本数据类型,而是引用数据类型时的情况
看以下例子:
1 class TestArray{
2 private int val = 10;
3 public void setVal(int val){
4 this.val = val;
5 }
6 public int getVal(){
7 return this.val;
8 }
9 }
10
11 public class TestDemo {
12 /**数组输出方法 */
13 public static void printArray(TestArray[] array){
14 for(int i = 0;i < array.length;i++){
15 System.out.print(array[i].getVal()+" ");
16 }
17 System.out.println();
18 }
19
20 public static void main(String[] args) {
21 TestArray[] array1 = new TestArray[3];
22 // 数组引用赋值
23 for (int i = 0; i < array1.length; i++){
24 array1[i] = new TestArray();
25 }
26
27 TestArray[] array2 = new TestArray[array1.length];
28 // 数组System.arraycopy()方法复制
29 System.arraycopy(array1,0,array2,0,array1.length);
30
31 printArray(array1);
32 printArray(array2);
33 System.out.println("==========");
34
35 array2[0].setVal(100);;
36 printArray(array1);
37 printArray(array2);
38 }
39 }
这段程序的结果是:
10 10 10
10 10 10
==========
100 10 10
100 10 10
由结果可以看出,当对复制数组的某个元素进行改变时,被复制数组对应元素也随之改变,即对于引用数据类型来说 System.arraycopy() 方法是浅拷贝。
三、Arrays.copyOf(浅拷贝)
这个方法也是浅拷贝,为什么呢?我们看一下它的源代码就知道了。
1 public static byte[] copyOfRange(byte[] original, int from, int to) {
2 int newLength = to - from;
3 if (newLength < 0)
4 throw new IllegalArgumentException(from + " > " + to);
5 byte[] copy = new byte[newLength];
6 System.arraycopy(original, from, copy, 0,Math.min(original.length - from, newLength));
7 return copy;
8 }
可以看到其实Arrays.copyOf()方法在底层是调用了 System.arraycopy() 方法来实现复制,即可以把Arrays.copyOf() 方法看作是 System.arraycopy() 方法的衍生方法,故它的执行机理与 System.arraycopy() 方法相同。 所以 Arrays.copyOf() 方法对于基本数据类型来说是深拷贝,对引用类型来说是浅拷贝。
四、对象拷贝(Object.clone)
clone()比较特殊,对于对象而言,它是深拷贝,但是对于数组而言,它是浅拷贝。 首先讲一下对象的拷贝,它是深拷贝,大家可以用对象去测试一下。下面我们看一下它的源代码:
1 protected native Object clone() throws CloneNotSupportedException;
这里也有native关键字,所以也是底层的c语言实现的。 还要注意的是,这里修饰符是protected,也就是说,我们创建了一个Object类以后,是不能直接调用这个clone()方法的,因为protected关键字只允许同一个包内的类和它的子类调用,所以我们声明一个object类时,肯定不是同一个包内,所以就不能去调用它。 要调用这个方法,就需要我们写一个类,然后声明实现cloneable接口就好了,不需要去显示地声明继承于object,因为java中的类如果不显示说明父类的话,默认父类就是object。然后我们继承这个方法:
1 @Override
2 public Object clone() throws CloneNotSupportedException {
3 // TODO Auto-generated method stub
4 return super.clone();
5 }
这里需要是,为了能够在不同包内去调用这个方法,我们需要把这个权限升级为public。现在我们就可以调用这个类的clone()方法去拷贝我们的类了。
五、数组拷贝
对于数组而言,它不是简单的将引用赋值为另外一个数组引用,而是创建一个新的数组。但是我们知道,对于数组本身而言,它它的元素是对象的时候,本来数组每个元素中保存的就是对象的引用,所以,拷贝过来的数组自然而言也是对象的引用,所以对于数组对象元素而言,它又是浅拷贝。我们用以下代码验证一下:
1 class Aby implements Cloneable{
2 public int i;
3 public Aby(int i) {
4 this.i = i;
5 }
6 @Override
7 public Object clone() throws CloneNotSupportedException {
8 // TODO Auto-generated method stub
9 return super.clone();
10 }
11 }
12 public class Solution {
13
14 public static void main(String[] args) throws CloneNotSupportedException {
15 Aby aby1 = new Aby(1);
16 Aby aby2 = (Aby) aby1.clone();
17 aby1.i = 2;
18 System.out.println(aby1.i); //2
19 System.out.println(aby2.i); //1
20
21 Aby[] arr = {aby1,aby2};
22
23 Aby[] arr2 = arr.clone();
24 arr2[0].i = 3;
25 System.out.println(arr[0].i); //3
26 System.out.println(arr2[0].i); //3
27 }
28 }
Java复制数组的方法的更多相关文章
- JAVA中复制数组的方法
在JAVA里面,可以用复制语句"A=B"给基本类型的数据传递值,但是如果A,B是两个同类型的数组,复制就相当于将一个数组变量的引用传递给另一个数组;如果一个数组发生改变,那么 引用 ...
- oracle调用JAVA类的方法
导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了, 1.操作系统需要拥有支持loadjava命令的jdk. 2.加 ...
- Java中的方法应用
一.如何定义java中的方法 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 语法: 1. 访问修饰符:方法允许被访问的权限范围, 可以是 public.protected.priv ...
- Java Runtime.availableProcessors()方法
Java Runtime.availableProcessors()方法用法实例教程. 描述 java.lang.Runtime.availableProcessors() 方法返回到Java虚拟 ...
- paip.java OutOfMemoryError 解决方法o33
paip.java OutOfMemoryError 解决方法o33 java.lang.OutOfMemoryError: Requested # java.lang.OutOfMemoryErro ...
- Java读写文件方法总结
Java读写文件方法总结 Java的读写文件方法在工作中相信有很多的用处的,本人在之前包括现在都在使用Java的读写文件方法来处理数据方面的输入输出,确实很方便.奈何我的记性实在是叫人着急,很多时候既 ...
- java调用本地方法的时候报错 could not find the main class:xx.program will exit
如图所示,当在java调用本地方法的时候报错 我的解决办法是把dll文件放到System.out.println(System.getProperty("java.library.path& ...
- 给NSString增加Java风格的方法
给NSString增加Java风格的方法 文章目录 我实在受不了 NSString 冗长的方法调用了,每次写之前都要查文档.特别是那个去掉前后多余的空格的方法,长得离谱.与之对应的别的语言,拿 jav ...
- Java基础——clone()方法浅析
一.clone的概念 clone顾名思义就是复制, 在Java语言中, clone方法被对象调用,所以会复制对象.所谓的复制对象,首先要分配一个和源对象同样大小的空间,在这个空间中创建一个新的对象.那 ...
随机推荐
- python3 进行接口测试
最近有研究接口测试,然后查了查资料,发现有两种方法,一种是使用urllib库,一种是使用requests库.而在这里,我使用的是requests库,为什么要用这个呢? 从官方文档看出,python的标 ...
- “酒香也怕巷子深” Smartflow-Sharp 工作流
导语 老话说得好,"酒香不怕巷子深"可是我又不是什么大咖,写得再好也没人知道.所以我今天准备再写写我的工作流组件,写得不好还请大家见谅.写文章对于我来说,有点感觉"茶壶里 ...
- # 095 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 03 封装总结 01 封装知识点总结
095 01 Android 零基础入门 02 Java面向对象 02 Java封装 01 封装的实现 03 # 088 01 Android 零基础入门 02 Java面向对象 02 Java封装 ...
- CF471D MUH and Cube Walls
Link 一句话题意: 给两堵墙.问 \(a\) 墙中与 \(b\) 墙顶部形状相同的区间有多少个. 这生草翻译不想多说了. 我们先来转化一下问题.对于一堵墙他的向下延伸的高度,我们是不用管的. 我们 ...
- TP5自定义路由,为了安全性
1,入口文件index.php,不要指定任意模块,不然,自定义路由,就不会有任何效果哦 2,在配置文件 route.php 中引进 use think\Router 自带路由文件 3,将路由进 ...
- Python+Appium自动化测试(4)-使用weditor进行元素定位
一,weditor的安装与使用 首选需要在电脑上配置好Python环境 下载安装命令如下,加上镜像下载速度更快: pip install weditor -i https://pypi.tuna.ts ...
- Cesium.Viewer
<!DOCTYPE html><html lang="en"><head> <meta charset="utf-8" ...
- golang常用库:字段参数验证库-validator
背景 在平常开发中,特别是在web应用开发中,为了验证输入字段的合法性,都会做一些验证操作.比如对用户提交的表单字段进行验证,或者对请求的API接口字段进行验证,验证字段的合法性,保证输入字段值的安全 ...
- Linux发行版教你如何选 给入门者的选择通法
Linux的发行版何止琳琅满目,简直是乱入你眼. 本篇将介绍选择发行版的经验和通用法则,主要会从PC角度去谈. 更新于2020年,初次发布于2017年 选择发行版需考虑哪些因素 选择发行版时需要考虑的 ...
- Go 安装配置golint
原文链接:http://zhoubotong.site/post/3.html一. Golint介绍 Golint 是一个源码检测工具用于检测代码规范 Golint 不同于gofmt, Gofmt用于 ...