java深度克隆大数据|java中如何实现一个类的深克隆的代码

❶ 如何使java中的InputStream的深层复制

我们知道在Java中存在这个接口Cloneable,实现该接口的类都会具备被拷贝的能力,同时拷贝是在内存中进行,在性能方面比我们直接通过new生成对象来的快,特别是在大对象的生成上,使得性能的提升非常明显。然而我们知道拷贝分为深拷贝和浅拷贝之分,但是浅拷贝存在对象属性拷贝不彻底问题。关于深拷贝、浅拷贝的请参考这里:渐析java的浅拷贝和深拷贝一、浅拷贝问题我们先看如下代码:[java] view plain public class Person implements Cloneable{ /** 姓名 **/ private String name; /** 电子邮件 **/ private Email email; public String getName() { return name; } public void setName(String name) { this.name = name; } public Email getEmail() { return email; } public void setEmail(Email email) { this.email = email; } public Person(String name,Email email){ this.name = name; this.email = email; } public Person(String name){ this.name = name; } protected Person clone() { Person person = null; try { person = (Person) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; } } public class Client { public static void main(String[] args) { //写封邮件 Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议…"); Person person1 = new Person("张三",email); Person person2 = person1.clone(); person2.setName("李四"); Person person3 = person1.clone(); person3.setName("王五"); System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent()); System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent()); System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent()); } } ——————– Output: 张三的邮件内容是:请与今天12:30到二会议室参加会议… 李四的邮件内容是:请与今天12:30到二会议室参加会议… 王五的邮件内容是:请与今天12:30到二会议室参加会议… 在该应用程序中,首先定义一封邮件,然后将该邮件发给张三、李四、王五三个人,由于他们是使用相同的邮件,并且仅有名字不同,所以使用张三该对象类拷贝李四、王五对象然后更改下名字即可。程序一直到这里都没有错,但是如果我们需要张三提前30分钟到,即把邮件的内容修改下:[java] view plain public class Client { public static void main(String[] args) { //写封邮件 Email email = new Email("请参加会议","请与今天12:30到二会议室参加会议…"); Person person1 = new Person("张三",email); Person person2 = person1.clone(); person2.setName("李四"); Person person3 = person1.clone(); person3.setName("王五"); person1.getEmail().setContent("请与今天12:00到二会议室参加会议…"); System.out.println(person1.getName() + "的邮件内容是:" + person1.getEmail().getContent()); System.out.println(person2.getName() + "的邮件内容是:" + person2.getEmail().getContent()); System.out.println(person3.getName() + "的邮件内容是:" + person3.getEmail().getContent()); } } 在这里同样是使用张三该对象实现对李四、王五拷贝,最后将张三的邮件内容改变为:请与今天12:00到二会议室参加会议…。但是结果是:[java] view plain 张三的邮件内容是:请与今天12:00到二会议室参加会议… 李四的邮件内容是:请与今天12:00到二会议室参加会议… 王五的邮件内容是:请与今天12:00到二会议室参加会议… 这里我们就疑惑了为什么李四和王五的邮件内容也发送了改变呢?让他们提前30分钟到人家会有意见的!其实出现问题的关键就在于clone()方法上,我们知道该clone()方法是使用Object类的clone()方法,但是该方法存在一个缺陷,它并不会将对象的所有属性全部拷贝过来,而是有选择性的拷贝,基本规则如下:1、 基本类型如果变量是基本很类型,则拷贝其值,比如int、float等。2、 对象如果变量是一个实例对象,则拷贝其地址引用,也就是说此时新对象与原来对象是公用该实例变量。3、 String字符串若变量为String字符串,则拷贝其地址引用。但是在修改时,它会从字符串池中重新生成一个新的字符串,原有紫都城对象保持不变。基于上面上面的规则,我们很容易发现问题的所在,他们三者公用一个对象,张三修改了该邮件内容,则李四和王五也会修改,所以才会出现上面的情况。对于这种情况我们还是可以解决的,只需要在clone()方法里面新建一个对象,然后张三引用该对象即可:[java] view plain protected Person clone() { Person person = null; try { person = (Person) super.clone(); person.setEmail(new Email(person.getEmail().getObject(),person.getEmail().getContent())); } catch (CloneNotSupportedException e) { e.printStackTrace(); } return person; } 所以:浅拷贝只是Java提供的一种简单的拷贝机制,不便于直接使用。对于上面的解决方案还是存在一个问题,若我们系统中存在大量的对象是通过拷贝生成的,如果我们每一个类都写一个clone()方法,并将还需要进行深拷贝,新建大量的对象,这个工程是非常大的,这里我们可以利用序列化来实现对象的拷贝。二、利用序列化实现对象的拷贝如何利用序列化来完成对象的拷贝呢?在内存中通过字节流的拷贝是比较容易实现的。把母对象写入到一个字节流中,再从字节流中将其读出来,这样就可以创建一个新的对象了,并且该新对象与母对象之间并不存在引用共享的问题,真正实现对象的深拷贝。[java] view plain public class CloneUtils { @SuppressWarnings("unchecked") public static <T extends Serializable> T clone(T obj){ T cloneObj = null; try { //写入字节流 ByteArrayOutputStream out = new ByteArrayOutputStream(); ObjectOutputStream obs = new ObjectOutputStream(out); obs.writeObject(obj); obs.close(); //分配内存,写入原始对象,生成新对象 ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); ObjectInputStream ois = new ObjectInputStream(ios); //返回生成的新对象 cloneObj = (T) ois.readObject(); ois.close(); } catch (Exception e) { e.printStackTrace(); } return cloneObj; } } 使用该工具类的对象必须要实现Serializable接口,否则是没有办法实现克隆的。[html] view plain public class Person implements Serializable{ private static final long serialVersionUID = 2631590509760908280L; ……………… //去除clone()方法 } public class Email implements Serializable{ private static final long serialVersionUID = 1267293988171991494L; ……………….. } 所以使用该工具类的对象只要实现Serializable接口就可实现对象的克隆,无须继承Cloneable接口实现clone()方法。

❷ java bean 如何过滤某些属性进行深度克隆

序列化,先写入,后读出。这两个bean 就毫无关系了。但内容一模一样。

publicSerializableObject(Serializablesobj){try{ByteArrayOutputStreambos=newByteArrayOutputStream();ObjectOutputStreamoos=newObjectOutputStream(bos);oos.writeObject(sobj);ByteArrayInputStreambis=newByteArrayInputStream(bos.toByteArray());ObjectInputStreamois=newObjectInputStream(bis);return(Serializable)ois.readObject();}catch(Exceptione){returnnull;}}

可以参考一下。不过 要求实现 Serializable接口。

原文:

http://tieba..com/p/3205322191

❸ java开发需要学习什么

Java 程序设计基础,包括 J2sdk基础、Java面向对象基础、Java API使用、数据结构及算法基础、Java AWT图形界面程序开发;J2SE平台Java程序设计,包括Swing图形程序设计, Socket网络应用程序设计,对象序列化,Java 常用数据结构,Applet,流和文件,多线程程序设计;……………………………… 看你问的问题,应该是对java很感兴趣,其实你可以自学java。关于如何学习java,我刚才看到一篇很不错的文章,是一个农民工介绍自己如何自学java,并找到Java的工作,里面介绍了他的学习方法和学习过程,希望对你有帮助。 我是一名地地道道的农民工,生活在经济落后的农村,有一个哥哥和一个弟弟,父母都是地道的农民,日出而作,日落而息,我从小到大学习一直很好,从小学到高一都,成绩在全级一直名列前茅,这样我也顺利了考上省的重点高中,然而,每个学期开学是家里最为难的时候,每次交学费都让父母发愁许久,家里为了给我筹钱读书,都借了不少钱,才让我读上高中。我知道我读到高中家里已经欠了好多债,为了减轻家里的负担,我选择了退学。 2009年我高一退学,为了给家里还债,干过建筑工地的小工,搞过塑料制品加工,送水工等等。很工资都很低,一个月也就1000多,加上加班费一个月能拿2000多一点,我每个月都向家里寄回800-1000元,到了2011年末,一次偶然的机会我接触了Java,听说Java的前景挺不错,工资相对于我一个农民工来说简直是天文数字,于是我在新华书店买了几本Java的书,尽管白天辛苦工作,晚上回来还是坚持看书,但有于基础太差很多都很不明白,但还是坚持看,一有看1-2个小时Java的书,看着看着许多基础都慢慢的学会了,但那些比较难的还是看不懂,后来还买了有些关于框架的书,还是看不懂,这样断断续续的持续了半年多,觉得自己Java的基础都差不多懂了,但框架还是看不懂,还有最缺的项目经验,看了很多招聘Java程序员的简介都要项目经验,相对我一个农民工来连框架都弄不明白,想找一份Java工作对我来说简直是奢侈。我只想学Java,并不敢想以后能从事Java的工作。 有一次,在网络上看到一篇让我很鼓舞的文章,是一个Java高手介绍在没有基础的朋友怎么自学入门Java,文章写的很好,包含了如何学习,该怎么学习,他提到一个方法就是看视频,因为看书实在太枯燥和费解的,不少是我们也看不懂,这点我真的很认同,我自己看书都看了很久才学会基础。曾经有想过参加培训,但是上万元的培训费让我望而却步,我工资这么低,每个月还有向家里汇钱,加上城市消费比较高,虽然每个月只有几百剩下,但是相对于上万万学费和四个月的吃住费用逼我连想不敢想。 于是我决定看视频,我就去搜索Java的视频,虽然我零星的找到一些Java的视频,但是都不系统。最重要连项目都没有。后来我找到一份很好的视频,是IT学习联盟这个网站一套视频叫<<零基础Java就业班>>(喜欢《零基础Java就业班》的可以复制 t.cn/8sx5z6L 粘贴浏览器地址栏按回车键即打开)的教程还不错,很完整。还赠送11个顶级企业项目。价格很合理,于是我买下来。 于是开始了我的自学Java的路,收到光盘后,我就开始学习,刚开始学习还不错,是从零基础教起,老师幽默风趣而又轻松的课堂教课,使我发现原来学习JAVA并不是一件很难的事情。因为我本来基础还不错,前面的基础看一篇我就过去了,到了框架,我觉不又不是很难,可能老师太牛了,他能把复杂的问题讲的比较通俗易懂,有些难点的地方我还是连续看了五六次,把他弄懂。每天下午6点下班后,吃了饭,马上跑回家。看视频,买了几本笔记本。当时,为了编程还花几百元了台二手的台式电脑,配置一般,但编程是足够的。一边看视频,一边记笔记,把重点都记下来,还一边跟着老师敲代码,为了能尽早学会Java。每天都坚持学5-6个小时。经常学到晚上一点多才睡觉。星期六,日不用上班,每天7点多起床,学到晚上11,12点。那段时间特别辛苦,特别累。在学习Java的三个多月里,除了吃饭睡觉工作,剩余的时间都在学习,因为我知道自己的计算机基础不是很好,也没有学过什么计算机,只是学了些Java基础,相对于那些科班的人来说我要比他们付出更多的努力。我只能咬紧牙关,坚持下去,我不能放弃,我要完成我的梦想,我要让我的家人过上好日子。终于三个多月后我把Java教程里的内容和项目都学完了,在学项目的过程中我发现项目特别重要,他能把你学过的知识全部联系起来,能更好的理解你所学的知识。还有学习过程中,动手很重要,要经常跟着老师动手敲,动手吧,跟着做,一行一行的跟着敲,再试着加一些自己的功能,按照自己的思路敲一些代码,收获远比干听大的多。 如果遇到暂时对于一些思路不能理解的,动手写,先写代码,慢慢你就会懂了。这套视频还赠送了11个顶级企业项目,对于我没有任何经验的人来说,这个太重要了,还有在学习项目是提升能力最快的方法。项目能把所有的知识点全都连到一起了,不再是分散的,而是形成一个整体了。那种感觉是仅仅深入钻研知识点而不写真实项目的人所不能体会的。一个项目就是一根绳子可以把大片的知识串到一起。 就这样,我用了两个月也把项目给学完了。其实学完教程差不错就达到就业水平,但是我可能觉得自己学历低还是把那11个顶级企业项目才去找工作。 接着我就到51job疯狂的投简历,因为我的学历问题,初中毕业,说真的,大公司没有人会要我。所以我头的都是民营的小公司,我希望自己的努力有所回报。没有想过几天后,就有面试了,但是第一次面试我失败了,虽然我自认为笔试很好,因为我之前做了准备,但是他们的要求比价严格,需要有一年的项目经验,所以我没有被选中。 后来陆续面试了几加公司,终于功夫不负有心人,我终于面试上了一家民营的企业。公司规模比较小,我的职务是Java程序员。我想我比较幸运,经理看中我的努力,就决定吕勇我,开的工资是3500一个月,虽然我知道在北京3500只能过温饱的生化,但是我想我足够了,比起以前的工资好了些,以后可以多寄些钱回家。我想只要我继续努力。我工资一定会翻倍的。 把本文写出来,希望能让和我一样的没有基础的朋友有信心,其实我们没有自卑,我们不比别人笨,只有我们肯努力,我们一样会成功。……………………………………

❹ 请问java中深度一个二维数组是什么意思怎么用代码实现

一个二维数组可以看成一个一维数组,每个元素存储一个一维数组首地址的引用,这个没问题吧!也就是说对于a[][],直接用b[][]=a,或者b[][]=a.clone() 都只是复制了一个引用(包括上面的array等方法),无法保证数据独立性,就是说a数组值改变会影响到b,反之亦然,这就是浅层复制。如果二维数组存放类型为基本类型,则只需要b的每一行进行复制(Object.clone()可以保证对基本类型做深层复制api上有写):b[][]=a.clone();//先利用浅层复制分配新的引用存放地址for(int i=0;i<a.length;i++){b[i]=a[i].clone();//a[i]指向数组的内容为基本类型,可以深层复制生成新引用对象}如果二维数组表示的是引用类型,则要对每一个元素调用clone(),并且保证所表示的引用类型遵循clone()复写原则。b[][]=a.clone();//先利用浅层复制分配新的引用存放地址for(int i=0;i<a.length;i++){for(int j=0;j<a[0].length;j++){b[i][j]=a[i][j].clone()//为每个元素进行深层复制}}以上是规范写法,实现方法有很多,但一定要记住,单纯的对引用的COPY是没有意义的,编程中要避免。

❺ java如何深度一个object

java深复制的例子:1、创建Employer类,实现Cloneable接口:class Employer implements Cloneable{ private String username; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }}2、创建Employee类,实现Cloneable接口,并改写clone方法,实现深复制:class Employee implements Cloneable{ private String username; private Employer employer; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Employer getEmployer() { return employer; } public void setEmployer(Employer employer) { this.employer = employer; } @Override public Object clone() throws CloneNotSupportedException { //克隆Employee对象并手动的进一步克隆Employee对象中包含的Employer对象 Employee employee = (Employee)super.clone(); employee.setEmployer((Employer) employee.getEmployer().clone()); return employee; }}3、这样,在客户端拷贝的两个Employee对象的Employer就互不影响了:public static void main(String[] args) throws CloneNotSupportedException { Employer employer = new Employer(); employer.setUsername("arthinking"); Employee employee = new Employee(); employee.setUsername("Jason"); employee.setEmployer(employer); //employee2由employee深复制得到 Employee employee2 = (Employee) employee.clone(); //这样两个employee各自保存了两个employer employee2.getEmployer().setUsername("Jason"); System.out.println(employee.getEmployer().getUsername()); System.out.println(employee2.getEmployer().getUsername());}

❻ java深度拷贝和浅度拷贝的问题

看来你并没来理解错克隆,反而源是改变东西的方法不对。先还是讲讲克隆吧。是的,上面的clone方法也就是Object的Clone方法是浅表复制,看看他的API说的:“此方法会创建此对象的类的一个新实例,并像通过分配那样,严格使用此对象相应字段的内容初始化该对象的所有字段;……。所以,此方法执行的是该对象的“浅表复制”,而不“深层复制”操作。 ”这你没理解错。但你测试的方法貌似有问题,让人不知你想干什么。本来sb1、sb2的a字段内容相同的。这两个字段代表两个对象,所谓俩对象,说白了实际上都是一个4字节空间,存的是StringBuffer对象地址,也就是所谓a对象,实际上包含两个东西,一个是a这个指针(我是在说JAVA),另一个指的是这个指针指向的堆栈里面的空间(再复杂就不说了,参阅《JAVA虚拟机》)。相同也就意味着两个变量指向的对象空间一样。这样的话,如果你调用sb1.a.put…类似的方法朝a中放东西,那sb2也会变。可你直接把sb1的a换了,也就是让a指向另一个你new的空间。这样和sb2有什么关系,而且你以后再改sb1的a,sb2也不会变。不说了,累。不懂就问我。

❼ java中的浅克隆和深克隆是什么

浅克隆:仅仅复制所克隆的对象,而不复制它所引用的对象。

被复制版对象的所有变量都含有与原来权的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。

深克隆:把要复制的对象所引用的对象都复制了一遍。

那些引用其他对象的变量将指向被复制过的新对象,而不再是原有的那些被引用的对象。

很明显二者时间消耗有差距,在不影响的情况下尽量用浅克隆

注意区分与C语言的浅克隆深克隆 那个是引用地址与重新分配地址构建的区别,详细可以参见:

http://www.cnblogs.com/yxnchinahlj/archive/2010/09/20/1831615.html

❽ java中如何实现一个类的深克隆的代码

类的属性如果是引用类型的 那么继续执行属性的 clone方法即可(属性要实现Cloneable接口)

❾ java Map深度复制问题

这里的是基础类型,不是引用类型,不需要拿出来单独复制,浅clone就可以了,但是attr这个map需要进行深度复制,因为这个是引用类型,复制后的对象修改该属性依然会影响源对象

clone方法可以简单写为

@Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub Elem elem = (Elem) super.clone(); Map<String, String> tempMap = new HashMap(); for (Entry<String, String> e : this.map.entrySet()) { /** * 这里的new String(e.getValue())可以直接用e.getValue()代替, * 写在这里仅仅是提醒当value是其他对象时需要做下处理,比如一个User对象,如果你直接写成 * tempMap.put(e.getKey(), e.getValue());那么肯定是没什么用的,而要写成 * tempMap.put(e.getKey(), e.getValue().clone()); */ tempMap.put(e.getKey(), new String(e.getValue())); } elem.map = tempMap; return elem; }

❿ java中深克隆与浅克隆的区别

深克隆与浅克隆大家知道,对象是互相引用的,即对象中可能包含了另一个对象的引用,举例如:有一个Order对象,Order对象中又包含了LineItems对象,然后LineItems对象又包含了Item对象。好了,现在我有一个Order对象order1,它包含了一个LineItems对象items,这表示的是有一个订单order1,订单的内容是items。好的,现在有另一个客户想要一份订单,内容跟order1完全一样,那么在系统的逻辑层我们怎么做呢?很简单,order2=order1.clone(). 我们知道clone方法是在内存中生成一个新的对象,而不是只得到原对象的引用。这时候,有人说话了:“哦,明白了我们对order2的成员变量进行修改,是不会影响order1的。” 很可惜,这句话只对了一半。假设order类有一个成员变量name,当然改变order2.name不会影响order1.name,因为他们在不同的内存区域。但是如果改变 order1.items呢?很遗憾,简单地使用order1.clone,是会影响到order2.items的。原因很简单,就是因为clone方法默认的是浅克隆,即不会克隆对象引用的对象,而只是简单地复制这个引用。所以在上例中,items对象在内存中只有一个,order1和order2都指向它,任何一个对象对它的修改都会影响另一个对象。那相对浅克隆,深克隆自然就是会克隆对象引用的对象了。也就是说,在上例中,改变order1.items并不会影响order2.items了。因为内存中有两个一样的items。如果实现深克隆?一个方法自然是重写clone方法,添加如order.items=(LineItems)items.clone()的语句,也就是人为地添加对引用对象的复制。这个方法的缺点是如果引用对象有很多,或者说引用套引用很多重,那么太麻烦了。业界常用的方法是使用串行化然后反串行化的方法来实现深克隆。由于串行化后,对象写到流中,所有引用的对象都包含进来了,所以反串行化后,对等于生成了一个完全克隆的对象。绝!这个方法的要求是对象(包括被引用对象)必须事先了Serializable接口,否则就要用transient关键字将其排除在复制过程中。

赞(0)