java list深拷贝_Java List 的深拷贝

老是会遇到深拷贝与浅拷贝的问题,这里进行了一些測试。代码例如以下:

/*

* To change this template, choose Tools | Templates

* and open the template in the editor.

*/

import java.io.ByteArrayInputStream;

import java.io.ByteArrayOutputStream;

import java.io.IOException;

import java.io.ObjectInputStream;

import java.io.ObjectOutputStream;

import java.io.Serializable;

import java.util.*;

/**

*

* @author User

*/

class Weiz implements Serializable{//对象序列化。要实现这个接口

private static final long serialVersionUID=123L;//序列化版本号

double x;

public Weiz(double a){

x=a;

}

}

public class test_copy {

/**

* @param args the command line arguments

*/

public static void main(String[] args) throws IOException, ClassNotFoundException {

// TODO code application logic here

List lst=new ArrayList();

lst.add(new Weiz(1.1));

lst.add(new Weiz(1.2));

lst.add(new Weiz(1.3));

System.out.println("复制前。原始lst:");

for(int i=0;i

System.out.println(lst.get(i)+" "+lst.get(i).x);

}

//System.out.println();

//构造函数复制 浅拷贝

List lst2=new ArrayList(lst);

//lst2.set(1, new Weiz(2.1));

lst2.get(0).x=2.1;

System.out.println("构造函数复制且改动后。新的lst2:");

for(int i=0;i

System.out.println(lst2.get(i)+" "+lst2.get(i).x);

}

System.out.println("构造函数复制且改动后,原始lst:");

for(int i=0;i

System.out.println(lst.get(i)+" "+lst.get(i).x);

}

List lst3=deepCopy(lst);

lst3.get(0).x=3.1;

System.out.println("对象序列化复制且改动后,新的lst3:");

for(int i=0;i

System.out.println(lst3.get(i)+" "+lst3.get(i).x);

}

System.out.println("对象序列化复制且改动后,原始lst:");

for(int i=0;i

System.out.println(lst.get(i)+" "+lst.get(i).x);

}

List lst4=deepCopy(lst);

lst4.get(0).x=4.1;

System.out.println("对象序列化复制且改动后。新的lst4:");

for(int i=0;i

System.out.println(lst4.get(i)+" "+lst4.get(i).x);

}

System.out.println("对象序列化复制且改动后。原始lst:");

for(int i=0;i

System.out.println(lst.get(i)+" "+lst.get(i).x);

}

}

//关键代码 运行序列化和反序列化 进行深度拷贝

public static List deepCopy(List src) throws IOException, ClassNotFoundException {

ByteArrayOutputStream byteOut = new ByteArrayOutputStream();

ObjectOutputStream out = new ObjectOutputStream(byteOut);

out.writeObject(src);

ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

ObjectInputStream in = new ObjectInputStream(byteIn);

@SuppressWarnings("unchecked")

List dest = (List) in.readObject();

return dest;

}

//关键代码 运行序列化和反序列化 进行深度拷贝,写法不同而已,作用一样

//个人习惯 怎么喜欢怎么来!

public List deepCopy2(List src) throws IOException, ClassNotFoundException{

ByteArrayOutputStream byteOut = new ByteArrayOutputStream();

ObjectOutputStream out = new ObjectOutputStream(byteOut);

out.writeObject(src);

ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());

ObjectInputStream in =new ObjectInputStream(byteIn);

List dest = (List)in.readObject();

return dest;

}

}

程序结果:

run:

复制前:

readdxflunwen.Weiz@c17164 1.1

readdxflunwen.Weiz@1fb8ee3 1.2

readdxflunwen.Weiz@61de33 1.3

构造函数复制且改动后,新的lst2:

readdxflunwen.Weiz@c17164 2.1

readdxflunwen.Weiz@1fb8ee3 1.2

readdxflunwen.Weiz@61de33 1.3

构造函数复制且改动后,原始lst:

readdxflunwen.Weiz@c17164 2.1

readdxflunwen.Weiz@1fb8ee3 1.2

readdxflunwen.Weiz@61de33 1.3

对象序列化复制且改动后。新的lst3:

readdxflunwen.Weiz@60aeb0 3.1

readdxflunwen.Weiz@16caf43 1.2

readdxflunwen.Weiz@66848c 1.3

对象序列化复制且改动后,原始lst:

readdxflunwen.Weiz@c17164 2.1

readdxflunwen.Weiz@1fb8ee3 1.2

readdxflunwen.Weiz@61de33 1.3

对象序列化复制且改动后,新的lst4:

readdxflunwen.Weiz@8813f2 4.1

readdxflunwen.Weiz@1d58aae 1.2

readdxflunwen.Weiz@83cc67 1.3

对象序列化复制且改动后。原始lst:

readdxflunwen.Weiz@c17164 2.1

readdxflunwen.Weiz@1fb8ee3 1.2

readdxflunwen.Weiz@61de33 1.3

成功构建 (总时间: 4 秒)

能够看到。用构造函数(旧List)的方法。是浅拷贝,拷贝的仅仅是List中的元素,即引用,而不是这些元素或引用指向的值。

而通过对象序列化方法,则是深拷贝,是把这些引用指向的对象又一次创建了一份的。

从打印的结果也能够看到。浅拷贝时,新list中元素的值和旧List是一样,即引用是一样的。而深拷贝时,新List中元素的值和旧List的是不一样的。即引用值是不一样的。你想一下。深拷贝是又一次创建了一份指向的对象。那么指向这个新对象的引用值当然和旧的应该是不一样的!

对象序列化方法是參考别的文章。链接Here。

当类实现了Serializable 接口,它的对象才是可序列化的。

实际上,Serializable 是一个空接口,它的目的仅仅是标识一个类的对象能够被序列化。

可序列化类中的属性serialVersionUID用于标识类的序列化版本号,若不显示定义该属性,JVM会依据类的相关信息计算它的值,而类改动后的计算结果与改动前的计算结果往往不同,这样反序列化时就会因版本号不兼容而失败。

假设一个类是可序列化的。则它的全部子类也是可序列化的。当序列化对象时,假设对象的属性又引用其它对象。则被引用的对象也必须是可序列化的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值