java深拷贝和浅拷贝的区别

Python016

java深拷贝和浅拷贝的区别,第1张

浅拷贝:只复制一个对象,对象内部存在的指向其他对象数组或者引用则不复制

深拷贝:对象,对象内部的引用均复制

示例:

public static Object copy(Object oldObj) {  

    Object obj = null  

    try {  

        // Write the object out to a byte array  

        ByteArrayOutputStream bos = new ByteArrayOutputStream()  

        ObjectOutputStream out = new ObjectOutputStream(bos)  

        out.writeObject(oldObj)  

        out.flush()  

        out.close()  

  

        // Retrieve an input stream from the byte array and read  

        // a copy of the object back in.  

        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray())   

        ObjectInputStream in = new ObjectInputStream(bis)  

        obj = in.readObject()  

    } catch (IOException e) {  

        e.printStackTrace()  

    } catch (ClassNotFoundException cnfe) {  

        cnfe.printStackTrace()  

    }  

    return obj  

}

java的多维数组的copy:希望采纳

class C{

public static void main(String args[]){

int a[][] = {{1,2,3},{4,5,6}}

int b[][] = new int[a.length][a[0].length]

System.arraycopy(a,0,b,0,a.length)//通过arraycopy()函数拷贝数组

b[0][0] = 4//改变数组b[0][0]的值

System.out.println("a[][]")

for(int i=0i<2i++){

for(int j=0j<3j++){

System.out.print(a[i][j]+" ")

}

System.out.println()

}

System.out.println("b[][]")

for(int i=0i<2i++){

for(int j=0j<3j++){

System.out.print(b[i][j]+" ")

}

System.out.println()

}

}

打印的结果如下:

a[][]

4 2 3

4 5 6

b[][]

4 2 3

4 5 6

而如果把上述程序中的二维数组改为一维数组,结果却不同。程序如下:

class C{

public static void main(String args[]){

int a[] = {1,2,3}

int b[] = new int[a.length]

System.arraycopy(a,0,b,0,a.length)//通过arraycopy()函数拷贝数组

b[0] = 4//改变数组b[0]的值

System.out.println("a[]:")

for(int i=0i<3i++){

System.out.print(a[i] + " ")

}

System.out.println()

System.out.println("b[]:")

for(int i=0i<3i++){

System.out.print(b[i] + " ")

}

}

}

打印结果如下:

a[]:

1 2 3

b[]:

4 2 3

第一个程序中,用b[0][0] =

4只改变了数组b[0][0]的值,可是结果却是数组a[0][0]的值也发生了改变。而在第二个程序中,由于是一个一维数组,改变了b[0]的

值,a[0]的值却并没有受到影响,所以问题可能就出在数组的维数上。第一个程序中的a 是一个数组的数组(java

中没有多维数组的概念,只有数组的数组),同理b 也是,那么a 含有两个元素,第一个是指向(1,2,3)

这个数组的引用,第二个是指向(4,5,6)这个数组的引用,而arrayCopy 就是负责把数组的内容copy 过去的,因此 a 的内容 (2

个引用) 被copy 到b 中去了,因此你对b[0][0] 做修改,a 也会同样跟着变化.

在JAVA里面,可以用复制语句“A=B”给基本类型的数据传递值,但是如果A,B是两个同类型的数组,复制就相当于将一个数组变量的引用传递给另一个数组;如果一个数组发生改变,那么引用同一数组的变量也要发生改变。

JAVA中复制数组元素值的的方法指深拷贝

1 使用for循环,将数组的每个元素复制(需要将每个对象调用clone方法,才能实现真正的复制)

2 使用clone方法,得到数组的值,而不是引用

3 使用System.arraycopy方法

注意:

1.上面方法中arraycopy效率较高。

2. 以上所说的拷贝数组的方法,只是针对一维数组,对于多维数组,要在每一维用以上方法进行复制才能实现复制数组元素的值而不是引用。

3. clone 和 arraycopy对二维数组进行复制时,是浅拷贝, 即

Object[][] aa

Object[][] bb = aa.clone()

//or bb=System.arraycopy(aa,0,bb, 0, bb.length)

则:

boolean b1 = ( aa[i] == bb[i] )//false

boolean b2 = (aa[i][j] == bb[i][j])//true, 可见数组元素只复制了引用。新旧数组指向相同的内存地址,(不论对象数组,还是基本类型数组)。

/**

* 数组的浅拷贝是指数组拷贝时,只拷贝了数组的地址,新旧数组指向同一数据

* 数组的深拷贝,不论数据是基本类型,还是对象类型,都是一样的。

* 对数组来说,不一样的地方在于,当为数组元素赋值时,基本类型值传递,对象类型是引用传递。

*

*/

Object[] a = new Object[]{"String", new Integer(1)}

Object[] b = a

/**

* 数组深拷贝的方法有如下几种:

* 1。 调用clone

* 2。 调用System.arraycopy

* 以上两种对基本类型和对象类型数据效果等同。

* 3。 使用FOR循环,将数组的每个元素复制。(注意调用clone方法)

*

*/

/*

* 当数组数据是基本类型时,

*/

// int[] array = new int[]{0,1,2,3,4}

// int[] copy = array.clone() //1.拷贝数据

// System.out.println( copy.equals(array))

// System.out.println( copy == array )

// for (int i = 0i <copy.lengthi++) {

// System.out.print( copy[i]+", " )

// copy[i]++//2.改变新数组数据内容

// System.out.print( copy[i]+", " )

// System.out.println( array[i]+",")//3.不影响原始数组

// }

// System.out.println()

/*

* 当数组数据是对象类型时,

*/

// Object[] src = new Object[]{ new String("Zhao"),

// Integer.valueOf(1),

// Integer.valueOf(2),

// Integer.valueOf(3),

// Integer.valueOf(4)}

//

// Object[] dest = src.clone()//1.拷贝数据

//

//// Object[] dest = new Object[5]

//// System.arraycopy(src, 0, dest, 0, dest.length)

//

// System.out.println( dest.equals(src))

// System.out.println( dest == src )

// for (int i = 0i <dest.lengthi++) {

// System.out.print( dest[i]+", " )

// dest[i] = new String("KE") //2.改变新数组内容

// System.out.print( dest[i]+", " )

// System.out.println( src[i]+",") //3.不影响原始数组

// }

// System.out.println()

/**

* 对多维数组(多维基本类型数组和多维对象数组完全一致。)

*

*/

//多维基本类型数组

int[][] aa = new int[][]{

{1, 2, 3},

{4, 5, 6},

{7, 8, 9}

}

// //多维对象类型数组

// Object[][] aa = new Object[][]{

// { Integer.valueOf(1),Integer.valueOf(2),Integer.valueOf(3) },

// { Integer.valueOf(4),Integer.valueOf(5),Integer.valueOf(6) },

// { Integer.valueOf(7),Integer.valueOf(8),Integer.valueOf(9) }

// }

/**

* 一维数组下的深拷贝在 多维数组 只是浅拷贝!!

*/

int[][] bb = aa.clone() //一维数组下的深拷贝,对于二维数组只是浅拷贝!!

// int[][] bb = new int[aa.length][aa[0].length]

// System.arraycopy(aa, 0, bb, 0, aa.length)

// Object[][] bb = aa.clone()

//// Object[][] bb = new Object[3][3]

//// System.arraycopy(aa, 0, bb, 0, aa.length) //一维数组下的深拷贝,对于二维数组只是浅拷贝!!

/**

* 二维数组的深拷贝的实现方式!!! 转为一维数组拷贝。

*/

// for (int i = 0i <bb.lengthi++) { //实现深拷贝的方法!!!!!!!!!!!!

// System.arraycopy(aa[i], 0, bb[i], 0, aa[i].length)

//// bb[i] = aa[i].clone()

// }

System.out.println("## 初始 aa:" ) //1. 初始原数组

for (int i = 0i <aa.lengthi++) {

for (int j = 0j <aa[i].lengthj++) {

System.out.print(aa[i][j]+" ")

}

System.out.println( )

}

System.out.println("## bb = aa.clone() 后bb:" )//2. 新数组(值等于原数组的值)

for (int i = 0i <bb.lengthi++) {

for (int j = 0j <bb[i].lengthj++) {

System.out.print(bb[i][j]+" ")

}

System.out.println( )

}

System.out.println("## bb改变后:" )//3.改变新数组后

for (int i = 0i <bb.lengthi++) {

for (int j = 0j <bb[i].lengthj++) {

bb[i][j] += 10//for 多维基本类型数组

// bb[i][j] = new String("Zhao")//for 多维对象类型数组

System.out.print(bb[i][j]+" ")

}

System.out.println( )

}

System.out.println("## bb改变后, aa:" ) //4.输出原数组

for (int i = 0i <aa.lengthi++) {

for (int j = 0j <aa[i].lengthj++) {

System.out.print(aa[i][j]+" ")

}

还有和c++不同,java定义int [][]a=new int[3][]是没有问题的,c和c++后面就是必须要有维数,int a[][3]。

如果list里面全是String[],转为String[][],使用

(String[][]) bodyDataList.toArray(new String[bodyDataList.size()][])这样就能转成功,还一直不清楚toArray(x)x里面的东西,因为java里面只有array对象

浅拷贝就是指对象复制的时候只复制一层;深拷贝是指复制对象的所有层级。

深拷贝和浅拷贝,主要是对象发生复制的时候,根据复制的层级不同来区分的。很多人在这里经常变量赋值发生混淆。对于JavaScript数组等复杂的数据类型来说,将其赋值给其它变量,其实只是复制了对象的地址给它,两个变量指向的是同一个对象,因此普通的赋值既不是深拷贝也不是浅拷贝。

深拷贝和浅拷贝需要注意的地方就是可变元素的拷贝:

在浅拷贝时,拷贝出来的新对象的地址和原对象是不一样的,但是新对象里面的可变元素(如列表)的地址和原对象里的可变元素的地址是相同的,也就是说浅拷贝它拷贝的是浅层次的数据结构(不可变元素),对象里的可变元素作为深层次的数据结构并没有被拷贝到新地址里面去。

而是和原对象里的可变元素指向同一个地址,所以在新对象或原对象里对这个可变元素做修改时,两个对象是同时改变的,但是深拷贝不会这样,这个是浅拷贝相对于深拷贝最根本的区别。