数组的拷贝及对象clone
1.前言
- java数组拷贝主要有四种方法,分别是循环赋值,System.arraycopy(), Arrays.copyOf()(或者Arrays.copyOfRange)和clone()方法。
- Java数组的复制操作可以分为深度复制和浅度复制。简单来说深度复制,可以将对象的值和对象的内容复制;浅复制是指对对象引用的复制。
2.代码详解
1. 循环拷贝(速度相对比较慢)
用一个for循环进行元素的逐个拷贝,进行深拷贝或者浅复制。
2. System.arraycopy(浅拷贝)
①系统提供的拷贝方式,也是我们推荐使用的拷贝方式,它是浅拷贝,也就是说对于非基本类型而言,它拷贝的是对象的引用,而不是去新建一个新的对象。通过它的代码我们可以看到,这个方法不是用java语言写的,而是底层用c或者c++实现的,因而速度会比较快。
②对于一维数组来说,这种复制属性值传递,修改副本不会影响原来的值。对于二维或者一维数组中存放的是对象时,复制结果是一维的引用变量传递给副本的一维数组,修改副本时,会影响原来的数组。
System.arraycopy的函数原型:
/**
*src表示源数组
*srcPos表示源数组要复制的起始位置
*desc表示目标数组
*length表示要复制的长度
*/
public static native void arraycopy(Object src, int srcPos,Object dest, int destPos,int length);
System.arraycopy()复制的过程图:
Demo[] demos = new Demo[]{new Demo(1, "aa"), new Demo(2, "bb")};
Demo[] demos2 =new Demo[demos.length];
System.arraycopy(demos, 0, demos2, 0, demos.length);
System.out.println("demos[0]="+demos[0].toString());
System.out.println("demos2[0]="+demos2[0].toString());
//此时demos[0]和demos2[0]的内容一致,均是"aa"
demos2[0].setName("cc");
System.out.println("demos2[0]="+demos2[0].toString());
System.out.println("demos[0]="+demos[0].toString());
//由于副本被修改为"cc",原来数组的内容也被修改为"cc"
3.Arrays.copyOf(浅拷贝)
函数原型:
public static byte[] copyOfRange(byte[] original, int from, int to) {
int newLength = to - from;
if (newLength < 0)
throw new IllegalArgumentException(from + " > " + to);
byte[] copy = new byte[newLength];
System.arraycopy(original, from, copy, 0,
Math.min(original.length - from, newLength));
return copy;
}
4.Object.clone
clone()比较特殊,对于对象而言,它是深拷贝,但是对于数组而言,它是浅拷贝。
慎用 Object的 clone方法来拷贝对象。对象的 clone方法默认是浅拷贝,若想实现深拷贝需要重写 clone方法实现属性对象
的拷贝。
①对象拷贝
因为protected关键字只允许同一个包内的类和它的子类调用,所以我们声明一个object类时,肯定不是同一个包内,所以就不能去调用它。
要调用这个方法,就需要我们写一个类,然后声明实现cloneable接口就好了,不需要去显示地声明继承于object,因为java中的类如果不显示说明父类的话,默认父类就是object。然后我们继承这个方法:
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
②数组拷贝
对于数组而言,它不是简单的将引用赋值为另外一个数组引用,而是创建一个新的数组。但是我们知道,对于数组本身而言,它它的元素是对象的时候,本来数组每个元素中保存的就是对象的引用,所以,拷贝过来的数组自然而言也是对象的引用,所以对于数组对象元素而言,它又是浅拷贝。
class Aby implements Cloneable{
public int i;
public Aby(int i) {
this.i = i;
}
@Override
public Object clone() throws CloneNotSupportedException {
// TODO Auto-generated method stub
return super.clone();
}
}
public class Solution {
public static void main(String[] args) throws CloneNotSupportedException {
Aby aby1 = new Aby(1);
Aby aby2 = (Aby) aby1.clone();
aby1.i = 2;
System.out.println(aby1.i); //2
System.out.println(aby2.i); //1
Aby[] arr = {aby1,aby2};
Aby[] arr2 = arr.clone();
arr2[0].i = 3;
System.out.println(arr[0].i); //3
System.out.println(arr2[0].i); //3
}
}
上一篇: ExtJS6.2开发-用户管理(一)
推荐阅读
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第7章:数组的定义与使用:课时29:数组与方法
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第7章:数组的定义与使用:课时26:数组引用传递分析
-
阿里Java学习路线:阶段 1:Java语言基础-Java面向对象编程:第7章:数组的定义与使用:课时34:对象数组
-
数组的拷贝及对象clone
-
【阿里云】Java面向对象开发课程笔记(二)——数组的定义与使用
-
关于Java数组查询的相关问题及实例 原创
-
浅谈Java中实现深拷贝的两种方式—clone() & Serialized
-
Java编程实现数组转成list及list转数组的方法
-
Python实现变量数值交换及判断数组是否含有某个元素的方法
-
jquery获取数组长度_js中dom对象和jQuery对象的相互转换