首页 > 编程语言 >Java 数组拷贝的几种方式

Java 数组拷贝的几种方式

时间:2022-11-25 21:12:19浏览次数:54  
标签:Java int System a1 Arrays a2 数组 拷贝

目前在Java中数据拷贝提供了如下方式:1、clone 2、System.arraycopy 3、Arrays.copyOf 4、Arrays.copyOfRange。

一、clone 方法

clone方法是从Object类继承过来的,基本数据类型(int ,boolean,char,byte,short,float ,double,long)都可以直接使用clone方法进行克隆,注意String类型是因为其值不可变所以也可以使用。

int 类型示例

int[] a1 = {1, 3};
int[] a2 = a1.clone();

a1[0] = 666;
System.out.println(Arrays.toString(a1));   //[666, 3]
System.out.println(Arrays.toString(a2));   //[1, 3]

String 类型示例

String[] a1 = {"a1", "a2"};
String[] a2 = a1.clone();

a1[0] = "b1"; //更改a1数组中元素的值
System.out.println(Arrays.toString(a1));   //[b1, a2]
System.out.println(Arrays.toString(a2));   //[a1, a2]

二、System.arraycopy

System.arraycopy方法是一个本地的方法,源码里定义如下:

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

其参数含义为:

(原数组, 原数组的开始位置, 目标数组, 目标数组的开始位置, 拷贝个数)

用法示例

int[] a1 = {1, 2, 3, 4, 5};
int[] a2 = new int[10];

System.arraycopy(a1, 1, a2, 3, 3);
System.out.println(Arrays.toString(a1)); // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(a2)); // [0, 0, 0, 2, 3, 4, 0, 0, 0, 0]

当使用这个方法的时候,需要复制到一个已经分配内存单元的数组。

三、Arrays.copyOf

Arrays.copyOf底层其实也是用的 System.arraycopy 源码,API 如下:

public static int[] copyOf(boolean[] original, int newLength)

参数含义:

(原数组,拷贝的个数)

用法示例

int[] a1 = {1, 2, 3, 4, 5};
int[] a2 = Arrays.copyOf(a1, 3);

System.out.println(Arrays.toString(a1)) // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(a2)) // [1, 2, 3]

使用该方法无需我们事先使用new关键字对对象进行内存单元的分配

四、Arrays.copyOfRange

Arrays.copyOfRange底层其实也是用的System.arraycopy,API 如下:

public static int[] copyOfRange(int[] original, int from, int to)

参数含义:

(原数组,开始位置,拷贝的个数)

用法示例:

int[] a1 = {1, 2, 3, 4, 5};
int[] a2 = Arrays.copyOfRange(a1, 0, 1);

System.out.println(Arrays.toString(a1)) // [1, 2, 3, 4, 5]
System.out.println(Arrays.toString(a2)) // [1]

最后需要注意的是基本类型的拷贝是不影响原数组的值的,如果是引用类型,就不能在这用了,因为数组的拷贝是浅拷贝,对于基本类型可以,对于引用类型是不适合的。

那么如何实现对象的深度拷贝呢?

五、实现对象的深度拷贝

实现Cloneable接口

实现Cloneable接口,并重写clone方法,注意一个类不实现这个接口,直接使用clone方法是编译通不过的。

/**
 * Created by Joe on 2018/2/13.
 */
public class Dog implements Cloneable {
    private String id;
    private String name;

	public Dog(String id, String name) {
        this.id = id;
        this.name = name;
    }

    // 省略 getter 、 setter 以及 toString 方法

    @Override
    public Dog clone() throws CloneNotSupportedException {
        Dog dog = (Dog) super.clone();

        return dog;
    }
}

示例:

Dog dog1 = new Dog("1", "Dog1");
Dog dog2 = dog1.clone();

dog2.setName("Dog1 changed");

System.out.println(dog1); // Dog{id='1', name='Dog1'}
System.out.println(dog2); // Dog{id='1', name='Dog1 changed'}

组合类深拷贝

如果一个类里面,又引用其他的类,其他的类又有引用别的类,那么想要深度拷贝必须所有的类及其引用的类都得实现Cloneable接口,重写clone方法,这样以来非常麻烦,简单的方法是让所有的对象实现序列化接口(Serializable),然后通过序列化反序列化的方法来深度拷贝对象。

public Dog myClone() {
	Dog dog = null;

	try {
		//将对象序列化成为流,因为写在流是对象里的一个拷贝
		//而原始对象扔在存在JVM中,所以利用这个特性可以实现深拷贝
		ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
		ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream);
		objectOutputStream.writeObject(this);

		//将流序列化为对象
		ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
		ObjectInputStream objectInputStream = new ObjectInputStream(byteArrayInputStream);
		dog = (Dog) objectInputStream.readObject();
	} catch (IOException | ClassNotFoundException e) {
		e.printStackTrace();
	}

	return dog;
}

参考

Java - 数组拷贝的几种方式

标签:Java,int,System,a1,Arrays,a2,数组,拷贝
From: https://www.cnblogs.com/lin546/p/16926352.html

相关文章

  • Java 序列化工具
    一、Java自带的序列化Java提供了一种对象序列化的机制,该机制中,一个对象可以被表示为一个字节序列,该字节序列包括该对象的数据、有关对象的类型的信息和存储在对象中数据......
  • Java学习六
    一.小结1.使用语法elemenrType[] arrayRefVar(元素类型[]数组引用变量)或elementType  arrayRefVar[](元素类型数组引用变量[])声明一个数组类型的变量。尽管e......
  • JavaScript中String的match方法详解
      String.prototype.match()**String.prototype.match()方法返回通过一个正则表达式匹配到的字符串结果。**varparagraph='Thequickbrownfoxjumpsove......
  • 对Java Web中WEB-INF目录的理解以及访问方法
    事情发生在上个暑假第一次写Javaweb大项目的时候,对于目录管理及分配没有任何经验,就想着清晰明了。后端servlet是用maven进行构建的,所以在目录上没有碰到什么大问题。用......
  • JAVA基础语法
    JAVA基础语法注释、标识符、关键字注释注释类似于笔记,程序是什么意思注释不会被执行书写注释是一个非常好习惯Java中注释分为单行注释,多行注释,文档注释平......
  • Java反射
    反射:框架设计的灵魂,将类的各个组成部分封装为其他对象,这就是反射机制。反射的好处:1.可以在程序运行过程中,操作这些对象2.可以解耦,提高程序的可扩展......
  • Java 中经常被提到的 SPI 到底是什么?
    layout:postcategories:Javatitle:Java中经常被提到的SPI到底是什么?tagline:by子悠tags:-子悠Java程序员在日常工作中经常会听到SPI,而且很多框架都使......
  • NEFU锐格作业一[数组-字符串]
    ​​推荐:NEFU大一下C语言锐格实验与作业参考程序目录​​文章目录​​NEFU锐格作业一[数组-字符串]​​​​知识点​​​​题目​​​​7132​​​​7124​​​​7150​​​......
  • js 字节数组模拟 agv auo
    res=JSON.stringify({x:10.0,y:3.0,angle:0});console.log(res);byteArr=[]for(letcofres){byteArr.push(c.charCodeAt().toString(16))}console......
  • java基础语法学习笔记
    java基础语法学习笔记数组定义的三种方法int[]array1={1,2,3,4,5};//定义一int[]array2=newint[10];//定义二int[]array3=newint[]{1,2,3,4,5};/......