Java数组专讲(深拷贝和浅拷贝)

一.数组的定义(是一个引用类型)

三种定义方式:

public static void main1(String[] args) {
        int[] array1 = {1, 2, 3, 4};
        int[] array2 = new int[]{1, 2, 3, 4}; //前两者是直接进行了初始化
        int[] array3 = new int[10];  //只在堆上分配了引用对象所指向地址的空间,没有初始化


    }

以上三种方式,其实array1 和 array2 都是一样的,array1 是 array2的简写,所以说我们的数组是需要new出来的!!!

我们都知道数组在Java中是引用数据类型,为什么呢?看下面👇

如果说一个基本的数据类型 比如直接就是 int a = 10,此时是在栈上开辟的空间,

而我们的数组是需要new出来的,而new出来的都会在堆上开辟空间。所以数组是引用数据类型!

所以说: 每创建一个数组,都会在栈和堆上开辟相应的空间,然后栈上的引用变量(比如下面的array1-->0x123)存的地址和堆上的地址(0x123)相同,所以通过array1就可以对数组进行操作。

看图片👇

先来看一组代码:

  public static void main2(String[] args) {
        //两个数组指向一个对象,然后选择一个进行对对象的修改
        int[] array1 = {1,2,3,4};
        array1[0] = 99;

        int[] array2 = array1; //此时array2 也指向 array1指向的引用地址;
        array2[0] = 100;  //array1指向的数组值被修改了
        System.out.println(Arrays.toString(array1));//{ 100,2,3,4}
        System.out.println(Arrays.toString(array2));//{ 100,2,3,4}

    }

以上代码中,最重要的是第三行代码,此时array2数组接收的是array1数组所指向对象的地址,也就是说代码执行到现在,array1 和 array2 都指向同一个对象,也就是{ 1 , 2 , 3 , 4 },所以运行结果都一样。看图:👇

如果明白了看下面代码:

   public static void main(String[] args) {
        //数组回收
        int[] array1 = {1,2,3,4};
        int[] array2 = {11,22,33,44};
        array1 = array2;// array1 也指向了 array2指向的地址 ,此时array1原来指向的数组被回收
        array1[0] = 100;
        System.out.println(Arrays.toString(array1));//100  22 33 44
        System.out.println(Arrays.toString(array2));// 100 22 33 44

    }

此时代码输出如上图,最重要的也是第三行代码,此时array1接受了array2对象的地址也就是两个引用同时指向了一个对象!所以此时array1 和 array2 都指向了 array2对象,也就是堆上的{ 11,22,33,44},所以array1修改值就会改变数组的值了。下面是图解:

二.数组作为参数进行传递

public static void func1(int[] array1) {
        array1 = new int[]{15,16,17};
    }
    public static void func2(int[] array2) {
        array2[0] = 99;
    }
    public static void main(String[] args) {
        int[] array = {1,2,3};
        func1(array);
        System.out.println(Arrays.toString(array));
        // func2(array);
    }

执行func1方法,此时输出的结果是怎样的?

我们看,array传进去之后,func1的形参array1接收到array的地址,此时两者都指向{1 , 2 , 3,}

然后array1又new了一下!此时array1又指向了新的对象 ,也就是{ 15 , 16 , 17 },所以最后的结果就是

如果运行func2方法呢? 大家有兴趣可以试一下!

总结:

1.当数组作为参数进行传递的时候,其实传的还是一个值!只不过这个值是堆上一个对象的地址!

2.使用数组作为参数进行传递,不一定改变实参的值,要看形参做了什么

        第一种情况:形参修改了实参指向对象的内容

        第二种情况:形参new了一个对象,这样就修改了自己的指向(本来是指向实参的)

三.数组元素的2倍

         也就是说将数组的元素每个都乘2,很简单

  public static int[] grow(int[] array) {
        int[] tmpArray = new int[array.length];//新定义一个数组存放2倍后的数组
        for (int i = 0; i < array.length; i++) {
            tmpArray[i] = array[i] * 2 ; //将原数组的每个元素*2后,放到新数组中
        }
        return tmpArray; //返回新数组
    }
    public static void main(String[] args) {
        //数组元素的二倍
        int[] array = {1,2,3,4,6,7,8};
        int[] ret = grow(array);
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(ret));
    }

这里写复杂是为了理解下面的数组拷贝的只是,此时运行结果是在下面:

ps:Array.toString(这里放数组!),是将括号里面的数组元素以字符串的形式打印出来!很方便!

此时的我们可以看到,array的元素没有被改变,因为返回的是新的数组,此时就是一个深拷贝

四.数组的拷贝(理解深拷贝和浅拷贝)

1.范围拷贝:

Arrays.copyOfRange(array, 1,3)

这个方法是左闭右开的,那下面代码举例,就是数组下标1~3的元素都拷贝走

但是其实是[ 1,3),也就是只会拷贝下标为1 和 2 的值到新数组

 public static void main(String[] args) {
        int[] array = {1, 2, 3, 4};
        int[] ret = Arrays.copyOfRange(array, 1,3);
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(ret));

        System.out.println("========");

        ret[0] = 999;

        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(ret));


    }

运行结果:

2.什么是深拷贝和浅拷贝?

简而言之:拷贝之后,通过新数组修改值,如果原数组的值也被改变, 就是浅拷贝

                  拷贝之后,通过新数组修改值,如果原数组的值没有被改变,就是深拷贝

3.深拷贝:

方法:  Arrays.copyOf(array, array.length)   拷贝数组的一个方法,可以记一下,和上面的范围拷贝有所不同 
int[] array1 = {1, 2, 3, 4};
int[] array2 = array1.clone();//另外一种方法,直接数组.clone  意思是直接拷贝原数组的副本
public static void main(String[] args) {
        int[] array = {1, 2, 3, 4};
        int[] ret = Arrays.copyOf(array, array.length);
        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(ret));

        System.out.println("========");

        ret[0] = 999;

        System.out.println(Arrays.toString(array));
        System.out.println(Arrays.toString(ret));


    }

运行结果:

ret数组就是拷贝了array数组的值,此时修改ret的值,array中的值不会发生改变,此时就是深拷贝

4.浅拷贝

这里不举例代码,直接看图

此时的array1 和 array 2 的每个元素 都指向对应的对象,此时不论通过array1还是array2修改对象的值,值都会发生改变,此时叫做浅拷贝!!!

总结:我只是个初学者,写的东西难免有疏漏或者不正确,请指正!

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值