Java对象深复制与浅复制实例详解
Java对象深复制与浅复制实例详解
我们在遇到一些业务场景的时候经常需要对对象进行复制,对于对象的复制一般有两种方式,深复制和浅复制
浅复制:对象的复制仅是对象本身,对象引用的其它对方并不会复制。
深复制:对象的复制包含对象引用的对象。
Java所有对象的基类提供了clone方法,但是这个方法是protectednative修饰,因此只暴露给之类去重写,外部是无法直接调用的。
我们现在来测试两种复制,首选是浅复制,浅复制要实现Cloneable接口。
//课程对象 classClass{ privateStringname; publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } } //学生对象 classUserimplementsCloneable{ privateStringname; privateLongid; //课程引用 privateClassc; publicClassgetC(){ returnc; } publicvoidsetC(Classc){ this.c=c; } publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } publicLonggetId(){ returnid; } publicvoidsetId(Longid){ this.id=id; } @Override protectedObjectclone()throwsCloneNotSupportedException{ returnsuper.clone(); } @Override publicinthashCode(){ returnsuper.hashCode(); } @Override publicbooleanequals(Objectobj){ if(objinstanceofUser){ Useruser=(User)obj; if(this.id==user.getId()&&this.getName()==user.getName()){ returntrue; } if(user.getId().equals(this.id) &&user.getName().equals(this.name)){ returntrue; } returnfalse; }else returnfalse; } }
我们来测试:
Useruser1=newUser(); Useruser2=user1; Useruser3=(User)user1.clone(); System.out.println(user1==user2); System.out.println(user3==user1); System.out.println(user3.equals(user1)); System.out.println(user3.getName()==user3.getName());//true,浅复制 Classc=newClass(); c.setName("语文"); user1.setC(c); //测试复制深度 Useruser4=(User)user1.clone(); System.out.println(user4.getC()==user1.getC());//true,说明引用的对象依然是同一个对象
对象的复制并没复制引用所指向的对象class,复制出来的引用指向的同一个地址。
深复制采用序列化与反序列的方式去获取,也有种说法类似于腌菜,用流的方式腌制进去又取出来,实现深度复制。
classCarimplementsSerializable{ /** * */ privatestaticfinallongserialVersionUID=42342L; privateStringname; publicStringgetName(){ returnname; } publicvoidsetName(Stringname){ this.name=name; } } //深复制 classPeopleimplementsSerializable{ /** * */ privatestaticfinallongserialVersionUID=543535212412L; privateCarcar; publicCargetCar(){ returncar; } publicvoidsetCar(Carcar){ this.car=car; } publicPeopledeepClone()throwsIOException,ClassNotFoundException{ //腌制 ByteArrayOutputStreamout=newByteArrayOutputStream(); ObjectOutputStreamoos=newObjectOutputStream(out); oos.writeObject(this); //取出 ByteArrayInputStreaminput=newByteArrayInputStream(out.toByteArray()); ObjectInputStreamois=newObjectInputStream(input); return(People)ois.readObject(); } }
测试深复制:
//深复制 Carcar=newCar(); car.setName("benz"); Peoplep=newPeople(); p.setCar(car); try{ Peoplep2=p.deepClone(); System.out.println(p2.getCar()==p.getCar());//false,说明引用的对象也进行了复制 }catch(ClassNotFoundException|IOExceptione){ e.printStackTrace(); }
例外提及一下生成对象的五种办法:
1.new
2.Class类的newInstance
3.Constructor类newInstance
4.Clone方式
5.反序列化的方式
其中2与3即是反射的方式。
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!