java对象深克隆_JAVA中对象的克隆及深拷贝和浅拷贝
使用場景:
在日常的編程過程 中,經常會遇到,有一個對象OA,在某一時間點OA中已經包含了一些有效值 ,此時可能會需一個和OA完全相對的新對象OB,并且要在后面的操作中對OB的任何改動都不會影響到OA的值,也就是OA與Ob是需要完全兩個獨立的對象。
但OB的初始值是由對象OA確定的。在JAVA語言中,用普通的賦值語句是滿足不了需求的。使用對象的clone()方法是實現克隆的最簡單、也是最高效的手段。
Java的所有類都默認繼承java.lang.Object類,在java.lang.Object類中有一個方法clone()。JDK API的說明文檔解釋這個方法將返回Object對象的一個拷貝。要說明的有兩點:一是拷貝對象返回的是一個新對象,而不是一個引用。二是拷貝對象與用 new操作符返回的新對象的區別就是這個拷貝已經包含了一些原來對象的信息,而不是對象的初始信息。 實現克隆可以用深拷貝和淺拷貝來實現。
深拷貝和淺拷貝的基本概念的理解:
淺拷貝是指拷貝對象時僅僅拷貝對象本身(包括對象中的基本變量),而不拷貝對象包含的引用指向的對象,被復制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。
深拷貝不僅拷貝對象本身,而且拷貝對象包含的引用指向的所有對象
通過實例看深拷貝和淺拷貝的實現和不同:
淺拷貝
class AddressNew implementsCloneable {privateString add;publicString getAdd() {returnadd;
}public voidsetAdd(String add) {this.add =add;
}public Object clone() throwsCloneNotSupportedException{return super.clone();
}
}public class StudentNew implementsCloneable{private intnumber;privateString name;publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}privateAddressNew addr;publicAddressNew getAddr() {returnaddr;
}public voidsetAddr(AddressNew addr) {this.addr =addr;
}public intgetNumber() {returnnumber;
}public void setNumber(intnumber) {this.number =number;
}public Object clone() throwsCloneNotSupportedException {return super.clone();
}
}public classJavaShallowCopy {public static void main(String [] args) throwsException{
AddressNew addr= newAddressNew();
addr.setAdd("杭州市");
StudentNew stu1= newStudentNew();
stu1.setNumber(123);
stu1.setName("s1");
stu1.setAddr(addr);
StudentNew stu2=(StudentNew)stu1.clone();
System.out.println("學生1:" + stu1.getNumber() + ",地址:" +stu1.getAddr().getAdd());
System.out.println("學生2:" + stu2.getNumber() + ",地址:" +stu2.getAddr().getAdd());
System.out.println(stu1);
System.out.println(stu2);
addr.setAdd("西湖區");//stu1.setNumber(20);//stu2.setName("s2");
System.out.println("學生1:" + stu1.getName() + ",地址:" +stu1.getAddr().getAdd());
System.out.println("學生2:" + stu2.getName() + ",地址:" +stu2.getAddr().getAdd());
}
}
運行結果:
學生1:123,地址:杭州市
學生2:123,地址:杭州市
com.songidea.StudentNew@133314b
com.songidea.StudentNew@b1bc7ed
學生1:s1,地址:西湖區
學生2:s1,地址:西湖區
從運行結果來看,stu1,stu2的解是2個不同的對象了,但是在改變了,addr的對象的地址之后,stu1,stu2的2個對象的引用對象addr的值都改變了,也就是說stu1和stu2的addr對象引用的是同一個地址,這個不是我們想要的結果,在實際的開發工作中這一塊一定要特別注意,使用不當可能會使業務功能或數據造成錯誤或混亂,所以這個拷貝只是實現在淺拷貝,那么從我們需要的場景看需要實現深拷貝才能達到我們想要的結果,下面會通過實例來看深拷貝的2種不同的實現。
深拷貝:
class Address implementsCloneable {privateString add;publicString getAdd() {returnadd;
}public voidsetAdd(String add) {this.add =add;
}
@OverridepublicObject clone() {
Address addr= null;try{
addr= (Address)super.clone();
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}returnaddr;
}
}public class Student implementsCloneable{private intnumber;privateString name;publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}privateAddress addr;publicAddress getAddr() {returnaddr;
}public voidsetAddr(Address addr) {this.addr =addr;
}public intgetNumber() {returnnumber;
}public void setNumber(intnumber) {this.number =number;
}
@OverridepublicObject clone() {
Student stu= null;try{
stu= (Student)super.clone(); //淺復制
}catch(CloneNotSupportedException e) {
e.printStackTrace();
}
stu.addr= (Address)addr.clone(); //深度復制
returnstu;
}
}public classjavaDeepCopy {public static voidmain(String args[]) {
Address addr = new Address();
addr.setAdd("杭州市");
Student stu1 = new Student();
stu1.setNumber(123);
stu1.setName("s1");
stu1.setAddr(addr);
Student stu2 = (Student) stu1.clone();
System.out.println("學生1:" + stu1.getNumber() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("學生2:" + stu2.getNumber() + ",地址:" + stu2.getAddr().getAdd());
System.out.println(stu1);
System.out.println(stu2);
addr.setAdd("西湖區");
stu1.setNumber(20);
System.out.println("學生1:" + stu1.getName() + ",地址:" + stu1.getAddr().getAdd());
System.out.println("學生2:" + stu2.getName() + ",地址:" + stu2.getAddr().getAdd());
} }
運行結果:
學生1:123,地址:杭州市
學生2:123,地址:杭州市
com.songidea.Student@133314b
com.songidea.Student@b1bc7ed
學生1:s1,地址:西湖區
學生2:s1,地址:杭州市
從運行結果來看,stu1,stu2的解是2個不同的對象了,在改變了addr的對象的地址之后,stu1,stu2的2個對象的引用對象addr的值只有stu1r 改變了,也就是說stu1和stu2的addr對象引用的不是同一個地址,這個是我們想要的結果所以這個拷貝只是實現在淺拷貝,那么從我們需要的場景看,這種方式實現了深拷,達到了我們想要的結果,下面會通過實例來看深拷貝的另一種實現:通過序例化來實現深拷貝。
深拷貝序列化的實現:
class AddressSerial implementsSerializable {privateString add;publicString getAdd() {returnadd;
}public voidsetAdd(String add) {this.add =add;
}
}public class StudentSerial implementsSerializable{private intnumber;privateString name;publicString getName() {returnname;
}public voidsetName(String name) {this.name =name;
}privateAddressSerial addr;publicAddressSerial getAddr() {returnaddr;
}public voidsetAddr(AddressSerial addr) {this.addr =addr;
}public intgetNumber() {returnnumber;
}public void setNumber(intnumber) {this.number =number;
}public Object clone() throwsCloneNotSupportedException {return super.clone();
}public Object deepClone() throwsIOException,OptionalDataException,ClassNotFoundException{
ByteArrayOutputStream bo=newByteArrayOutputStream();
ObjectOutputStream oo=newObjectOutputStream(bo);
oo.writeObject(this);
ByteArrayInputStream bi=newByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi=newObjectInputStream(bi);returnoi.readObject();
}
}public classjavaDeepCopySreial {public static void main(String [] args) throwsException{
AddressSerial addr= newAddressSerial();
addr.setAdd("杭州市");
StudentSerial stu1= newStudentSerial();
stu1.setNumber(123);
stu1.setName("s1");
stu1.setAddr(addr);
StudentSerial stu2=(StudentSerial)stu1.deepClone();
System.out.println("學生1:" + stu1.getNumber() + ",地址:" +stu1.getAddr().getAdd());
System.out.println("學生2:" + stu2.getNumber() + ",地址:" +stu2.getAddr().getAdd());
System.out.println(stu1);
System.out.println(stu2);
addr.setAdd("西湖區");//stu1.setNumber(20);//stu2.setName("s2");
System.out.println("學生1:" + stu1.getName() + ",地址:" +stu1.getAddr().getAdd());
System.out.println("學生2:" + stu2.getName() + ",地址:" +stu2.getAddr().getAdd());
}
}
運行結果:
學生1:123,地址:杭州市
學生2:123,地址:杭州市
com.songidea.StudentSerial@1e80bfe8
com.songidea.StudentSerial@5e9f23b4
學生1:s1,地址:西湖區
學生2:s1,地址:杭州市
從運行的結果看序例化也達到了深拷貝的場景。
參考和閱讀的幾偏深拷貝淺拷貝的文章:
https://www.cnblogs.com/null00/archive/2010/12/14/2065088.html
https://www.cnblogs.com/xuanxufeng/p/6558330.html
https://blog.csdn.net/baiye_xing/article/details/71788741
總結
以上是生活随笔為你收集整理的java对象深克隆_JAVA中对象的克隆及深拷贝和浅拷贝的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 计算机专业课程群建设,计算机科学与技术专
- 下一篇: 两个分布的特征映射_跨语言分布表示学习方