东莞英文网站设计,网站后台管理系统的主要功能,求网址直接能看的2021,2022年企业所得税税率我们知道在Java中存在这个接口Cloneable#xff0c;实现该接口的类都会具备被拷贝的能力#xff0c;同时拷贝是在内存中进行#xff0c;在性能方面比我们直接通过new生成对象来的快#xff0c;特别是在大对象的生成上#xff0c;使得性能的提升非常明显。然而我们知道拷贝…我们知道在Java中存在这个接口Cloneable实现该接口的类都会具备被拷贝的能力同时拷贝是在内存中进行在性能方面比我们直接通过new生成对象来的快特别是在大对象的生成上使得性能的提升非常明显。然而我们知道拷贝分为深拷贝和浅拷贝之分但是浅拷贝存在对象属性拷贝不彻底问题。关于深拷贝、浅拷贝的请参考这里渐析java的浅拷贝和深拷贝一、浅拷贝问题我们先看如下代码public class Person implementsCloneable{/**姓名 **/privateString name;/**电子邮件 **/privateEmail email;publicString getName() {returnname;}public voidsetName(String name) {this.name name;}publicEmail getEmail() {returnemail;}public voidsetEmail(Email email) {this.email email;}publicPerson(String name,Email email){this.name name;this.email email;}publicPerson(String name){this.name name;}protectedPerson clone() {Person person null;try{person (Person) super.clone();}catch(CloneNotSupportedException e) {e.printStackTrace();}returnperson;}}public classClient {public static voidmain(String[] args) {//写封邮件Email email new Email(请参加会议,请与今天12:30到二会议室参加会议...);Person person1 new Person(张三,email);Person person2person1.clone();person2.setName(李四);Person person3person1.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分钟到即把邮件的内容修改下public classClient {public static voidmain(String[] args) {//写封邮件Email email new Email(请参加会议,请与今天12:30到二会议室参加会议...);Person person1 new Person(张三,email);Person person2person1.clone();person2.setName(李四);Person person3person1.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到二会议室参加会议...。但是结果是张三的邮件内容是请与今天12:00到二会议室参加会议...李四的邮件内容是请与今天12:00到二会议室参加会议...王五的邮件内容是请与今天12:00到二会议室参加会议...这里我们就疑惑了为什么李四和王五的邮件内容也发送了改变呢让他们提前30分钟到人家会有意见的其实出现问题的关键就在于clone()方法上我们知道该clone()方法是使用Object类的clone()方法但是该方法存在一个缺陷它并不会将对象的所有属性全部拷贝过来而是有选择性的拷贝基本规则如下1、 基本类型如果变量是基本很类型则拷贝其值比如int、float等。2、 对象如果变量是一个实例对象则拷贝其地址引用也就是说此时新对象与原来对象是公用该实例变量。3、 String字符串若变量为String字符串则拷贝其地址引用。但是在修改时它会从字符串池中重新生成一个新的字符串原有紫都城对象保持不变。基于上面上面的规则我们很容易发现问题的所在他们三者公用一个对象张三修改了该邮件内容则李四和王五也会修改所以才会出现上面的情况。对于这种情况我们还是可以解决的只需要在clone()方法里面新建一个对象然后张三引用该对象即可protectedPerson clone() {Person person null;try{person (Person) super.clone();person.setEmail(newEmail(person.getEmail().getObject(),person.getEmail().getContent()));}catch(CloneNotSupportedException e) {e.printStackTrace();}returnperson;}所以浅拷贝只是Java提供的一种简单的拷贝机制不便于直接使用。对于上面的解决方案还是存在一个问题若我们系统中存在大量的对象是通过拷贝生成的如果我们每一个类都写一个clone()方法并将还需要进行深拷贝新建大量的对象这个工程是非常大的这里我们可以利用序列化来实现对象的拷贝。二、利用序列化实现对象的拷贝如何利用序列化来完成对象的拷贝呢在内存中通过字节流的拷贝是比较容易实现的。把母对象写入到一个字节流中再从字节流中将其读出来这样就可以创建一个新的对象了并且该新对象与母对象之间并不存在引用共享的问题真正实现对象的深拷贝。public classCloneUtils {SuppressWarnings(unchecked)public static T clone(T obj){T cloneObj null;try{//写入字节流ByteArrayOutputStream out newByteArrayOutputStream();ObjectOutputStream obs newObjectOutputStream(out);obs.writeObject(obj);obs.close();//分配内存写入原始对象生成新对象ByteArrayInputStream ios newByteArrayInputStream(out.toByteArray());ObjectInputStream ois newObjectInputStream(ios);//返回生成的新对象cloneObj (T) ois.readObject();ois.close();}catch(Exception e) {e.printStackTrace();}returncloneObj;}}使用该工具类的对象必须要实现Serializable接口否则是没有办法实现克隆的。public class Person implementsSerializable{private static final long serialVersionUID 2631590509760908280L;..................//去除clone()方法}public class Email implementsSerializable{private static final long serialVersionUID 1267293988171991494L;....................}所以使用该工具类的对象只要实现Serializable接口就可实现对象的克隆无须继承Cloneable接口实现clone()方法。public classClient {public static voidmain(String[] args) {//写封邮件Email email new Email(请参加会议,请与今天12:30到二会议室参加会议...);Person person1 new Person(张三,email);Person person2CloneUtils.clone(person1);person2.setName(李四);Person person3CloneUtils.clone(person1);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());}}-------------------Output:张三的邮件内容是请与今天12:00到二会议室参加会议...李四的邮件内容是请与今天12:30到二会议室参加会议...王五的邮件内容是请与今天12:30到二会议室参加会议...巩固基础提高技术不惧困难攀登高峰参考文献《编写高质量代码 改善Java程序的151个建议》----秦小波