`
qindongliang1922
  • 浏览: 2189410 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
7265517b-f87e-3137-b62c-5c6e30e26109
证道Lucene4
浏览量:117687
097be4a0-491e-39c0-89ff-3456fadf8262
证道Hadoop
浏览量:126086
41c37529-f6d8-32e4-8563-3b42b2712a50
证道shell编程
浏览量:60040
43832365-bc15-3f5d-b3cd-c9161722a70c
ELK修真
浏览量:71414
社区版块
存档分类
最新评论

Java里面关于数组拷贝的几种方式

    博客分类:
  • JAVA
阅读更多


在java里面数组拷贝有几种方式:

(1)clone

(2)System.arraycopy

(3)Arrays.copyOf

(4)Arrays.copyOfRange





下面分别介绍下他们的用法:



(1)clone方法是从Object类继承过来的,基本数据类型(String,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]

 
````



(2)System.arraycopy方法是一个本地的方法,源码里定义如下:
````
  public static native 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]
````


注意这个方法,需要我们自己new一个新的数组

(3)Arrays.copyOf底层其实也是用的System.arraycopy
源码如下:
````
    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;
    }
````


参数含义:

(原数组,拷贝的个数)


用法示例:

````
 `       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新的数组



(4)Arrays.copyOfRange底层其实也是用的System.arraycopy,只不过封装了一个方法

参数含义:

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


用法示例:
````
`       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]
````




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


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


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


````
public class Dog implements Cloneable {

    private String id;
    private String name;
    
    //省略getter / setter
    
    
    
    @Override
    public Dog clone() throws CloneNotSupportedException {

       Dog dog=(Dog)        super.clone();

       return dog;

    }
    
    }
````


示例:

````
`       Dog d1=new Dog("1","dog1");
        Dog d2=d1.clone();

        d1.setName("dog1_change");


        System.out.println(d1);//Dog{id='1', name='dog1_change'}
        System.out.println(d2);//Dog{id='1', name='dog1'}

````


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


````
   public Dog myclone() {
 6       Dog dog = null;
 7       try { // 将该对象序列化成流,因为写在流里的是对象的一个拷贝,而原对象仍然存在于JVM里面。所以利用这个特性可以实现对象的深拷贝
 8           ByteArrayOutputStream baos = new ByteArrayOutputStream();
 9           ObjectOutputStream oos = new ObjectOutputStream(baos);
10           oos.writeObject(this);
11       // 将流序列化成对象
12           ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
13           ObjectInputStream ois = new ObjectInputStream(bais);
14           dog = (Dog) ois.readObject();
15       } catch (IOException e) {
16           e.printStackTrace();
17       } catch (ClassNotFoundException e) {
18           e.printStackTrace();
19       }
20       return dog;
21   }
````





总结:

本文介绍了关于Java里面的数组拷贝的几种方式和用法,并给出了如何在Java里面实现对象的深度拷贝,注意除非必需,一般情况下不要使用对象的深度拷贝,因为性能较差。除了自己实现深度拷贝的功能外,网上也有一些开源的工具类也集成了这些功能,如Apache Common Lang3,但原理都大同小异,感兴趣的同学可以自己去学习下。

有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。 技术债不能欠,健康债更不能欠, 求道之路,与君同行。








0
0
分享到:
评论

相关推荐

    dotnet 6 数组拷贝性能对比.rar

    首先,我们要知道在C#中,有几种不同的方法可以实现数组拷贝: 1. **Array.Copy()**:这是.NET框架提供的一个静态方法,用于从源数组的一部分复制到目标数组中。这种方法适用于不同类型的数组,只要它们的元素类型...

    java 复制数组的资源

    有几种不同的方法可以实现数组的复制,每种方法都有其特定的适用场景。以下将详细阐述Java中复制数组的主要方法: 1. **浅拷贝(Shallow Copy)**: - `System.arraycopy()`:这是Java中最直接、最高效的方式来...

    java-数组与方法及面向对象基础

    Java是一种广泛使用的编程语言,以其跨平台、面向对象的特点深受开发者喜爱。本教程将深入探讨Java中的数组、方法以及面向对象编程的基础概念,为初学者提供一个全面的学习指南。 一、数组 数组在Java中是存储同一...

    Java数组练习题(带答案).doc

    本文将围绕Java数组进行详细介绍,并辅以示例来加深理解。 首先,我们要了解数组的访问机制。数组是一种线性数据结构,其元素通过整数索引进行访问。数组在声明时需要指定元素类型和数组大小,一旦创建完成,其长度...

    数组概述和特点

    数组操作还包括数组拷贝,如使用`System.arraycopy()`方法,或利用`java.util.Arrays`类提供的工具方法。例如,打印数组内容: ```java int[] a = {1, 2}; System.out.println(Arrays.toString(a)); // [1, 2] ``` ...

    java代码-数组 40 李启强

    下面,我们将详细讨论Java数组的相关知识点。 1. **数组定义**:数组是由相同类型的元素序列组成的复合数据类型。在Java中,我们可以通过以下方式声明数组: ```java 数据类型[] arrayName; 或 数据类型 ...

    数组参数学习内容

    在编程世界中,数组是一种非常基础且重要的数据结构,它允许我们存储一组相同类型的数据。在函数调用中,有时我们需要传递多个值给一个函数,这时数组参数就显得尤为重要。本学习内容主要聚焦于“数组参数”,让我们...

    android定义数组

    首先,我们要了解在Java中,有几种类型的数组可供选择:一维数组、二维数组以及多维数组。在Android开发中,主要是使用Java语言,所以这里主要讨论Java中的数组。 1. 一维数组: 一维数组是最基本的数组形式,可以...

    Java中内存分配的几种方法

    Java数组的大小受到`int`类型的限制,因为数组的索引是`int`类型。这意味着最大数组大小不能超过`Integer.MAX_VALUE`(2^31 - 1),约2GB。但你可以创建更大元素类型(如`long`)的数组,即使这样可能会导致实际...

    java代码-lsy数组比

    在"java代码-lsy数组比"这个主题中,我们可以推测这可能是关于比较或操作Java数组的一些代码示例。让我们深入探讨一下Java中的数组以及可能涉及的概念。 1. **数组定义与声明**: 在Java中,数组的定义包括指定...

    拼接byte数组

    在Java中,拼接`byte`数组可以通过以下几种方式实现: 1. **使用`System.arraycopy()`**: 这是Java中最常用的方法,它可以从源数组中复制指定范围的元素到目标数组中。例如,假设我们有两个`byte`数组`arr1`和`...

    java对象复制克隆

    在Java中实现深拷贝,我们可以有以下几种方法: 1. **实现Serializable接口**:这是通过序列化和反序列化实现深拷贝的方法。首先将对象转换为字节数组,然后从这个字节数组中反序列化出一个新的对象。这种方法简单...

    大数据必学Java基础(二十四):数组的引入和学习

    在Java编程语言中,数组是一种非常基础且重要的数据结构,特别是在大数据处理中,对大量数据的高效管理和操作离不开数组的应用。本节我们将深入探讨数组的引入和学习。 首先,数组的引入是为了解决特定问题,例如在...

    java笔记 java笔记

    Java支持以下几种数据类型: - **基本类型**:如int、float、char等。 - **引用类型**:如类、数组等。 ##### 3.5 命名规则 - 类名首字母大写。 - 变量名首字母小写。 - 方法名首字母小写,采用驼峰命名法。 ####...

    java考试复习资料

    Java支持以下几种基本数据类型: - **整型**:`byte`, `short`, `int`, `long` - **浮点型**:`float`, `double` - **字符型**:`char` - **布尔型**:`boolean` #### 十一、类型转换 - **隐式转换**:自动地从小...

    Java语言编程-常用类

    Java提供了多个类来协助数组的操作,其中`System`类中的`arrayCopy()`方法可以用来拷贝数组,而`Arrays`类则提供了多种静态方法来操作数组,如排序、搜索等。 在处理数组时,需要注意两种常见的异常:`...

    MyBatisDemo && JAVA把一个对象的全部属性复制到另一个相同的对象

    在Java中,我们可以通过以下几种方法实现对象的深拷贝: 1. **实现Serializable接口**:利用序列化和反序列化来实现深拷贝。首先将对象序列化为字节数组,然后再将这个字节数组反序列化为新的对象。这种方法适用于...

    Java 基础核心总结 +经典算法大全.rar

    关于 null 的几种处理方式大小写敏感 null 是任何引用类型的初始值 null 只是-种特殊的值使用 Null-Safe 方法null 判断 关于思维导图 Java.IO Java.lang Java.math Java.net Java 基础核心总结 V2.0 IO 传统的 ...

    顺序栈通常使用数组来实现,其特点是在栈底预先分配好一块存储空间,栈顶指针指向栈顶元素 以下是一个简单的Java实现:.txt

    在实际开发中,根据需要也可以对顺序栈进行扩展,比如增加栈的容量(数组扩容通常涉及数组拷贝),或者实现一个支持迭代的栈,以便于进行遍历操作等。此外,Java标准库中提供了`java.util.Stack`类,它也是基于数组...

    java全集.pdf JAVA全集

    **5.5 数组拷贝** - 可以使用`System.arraycopy()`方法或者`Arrays.copyOf()`方法来复制数组。 #### 六、对象和类 **6.1 面向对象与面向过程** - **面向对象**:将数据和操作数据的方法封装在一起。 - **面向...

Global site tag (gtag.js) - Google Analytics