java数组复制的问题

java 数组内存地址

数组:引用类型

    int[] a=null;//声明数组,也是引用
    a=new int[5];//分配内存地址。

数组的引用
第一步,当声明数组时在栈中开辟一个地址空间 ,即a的引用地址
第二步,在堆中开辟一系统连续的地址,具体的需要根据你的类型还有数组长度 ,即0x0123
java数组复制的问题
总结下,数组的引用保存在栈中,同时实例的时候在堆中开辟连续空间,栈中的空间指向堆的首地址。

栈内存

在方法中定义的一些基本类型的变量和对象的引用变量都在方法的栈内存中分配,当在一段代码中定义一个变量时,java就在栈内存中为这个变量分配内存空间,当超出变量的作用域后,java会自动释放掉为该变量所分配的内存空间。

堆内存

堆内存用来存放由new运算符创建的对象和数组,在堆中分配的内存,由java虚拟机的自动垃圾回收器来管理。在堆中创建了一个数组或对象后,同时还在栈内存中定义一个特殊的变量。让栈内存中的这个变量的取值等于数组或者对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量,引用变量实际上保存的是数组或对象在堆内存中的地址(也称为对象的句柄),以后就可以在程序中使用栈的引用变量来访问堆中的数组或对象。

浅克隆

    int[] d={1,2};
    int[] t= new int[2];
    t=d;
    d[0]=2;
    System.out.println(t[0]);

输出 2
此时 t=d 只是将d[]的 引用地址复制给 t[] ,所以改变d[]中的值, t[]也会改变,这是浅克隆

java数组复制的问题

深克隆

    int[] d={1,2};
    int[] t= new int[2];
    t=d.clone();
    d[0]=2;
    System.out.println(t[0]);

输出 1
clone是对一维数组的深度复制,会重新创建对象
java数组复制的问题

浅克隆(shadow clone)
只需要复制对象的字段值,对于8种基本类型,如int,long,float等,则复制值;对于复合数据类型仅复制该字段值,如数组则复制地址,对于对象变量则复制对象的reference。

深克隆(deep clone)
深克隆和浅克隆的区别在于复合数据类型的复制。若对象中的某个字段为复合类型,在克隆对象的时候,需要为该字段重新创建对象。

小结:
数组的复制方法:

  1. 使用循环结构
  2. 使用Object类的clone()方法, 这种方法最简单,得到原数组的一个副本。