面試官:來點基礎的,你來說說Java深拷貝和淺拷貝區(qū)別嗎?

一、拷貝的引入
(1)、引用拷貝
創(chuàng)建一個指向對象的引用變量的拷貝。
Teacher?teacher?=?new?Teacher("Taylor",26);
Teacher?otherteacher?=?teacher;
System.out.println(teacher);
System.out.println(otherteacher);
輸出結果:
blog.Teacher@355da254
blog.Teacher@355da254
結果分析:由輸出結果可以看出,它們的地址值是相同的,那么它們肯定是同一個對象。teacher和otherteacher的只是引用而已,他們都指向了一個相同的對象Teacher(“Taylor”,26)。這就叫做引用拷貝。往期:一百期面試題匯總

(2)、對象拷貝
創(chuàng)建對象本身的一個副本。
Teacher?teacher?=?new?Teacher("Swift",26);?
Teacher?otherteacher?=?(Teacher)teacher.clone();?
System.out.println(teacher);
System.out.println(otherteacher);
輸出結果:
blog.Teacher@355da254
blog.Teacher@4dc63996
結果分析:由輸出結果可以看出,它們的地址是不同的,也就是說創(chuàng)建了新的對象, 而不是把原對象的地址賦給了一個新的引用變量,這就叫做對象拷貝。

注:深拷貝和淺拷貝都是對象拷貝
二、淺拷貝
(1)、定義
被復制對象的所有變量都含有與原來的對象相同的值,而所有的對其他對象的引用仍然指向原來的對象。即對象的淺拷貝會對“主”對象進行拷貝,但不會復制主對象里面的對象。”里面的對象“會在原來的對象和它的副本之間共享。往期:100期面試題匯總
簡而言之,淺拷貝僅僅復制所考慮的對象,而不復制它所引用的對象
(2)、淺拷貝實例
package?com.test;
public?class?ShallowCopy?{
????public?static?void?main(String[]?args)?throws?CloneNotSupportedException?{
????????Teacher?teacher?=?new?Teacher();
????????teacher.setName("riemann");
????????teacher.setAge(27);
????????Student2?student1?=?new?Student2();
????????student1.setName("edgar");
????????student1.setAge(18);
????????student1.setTeacher(teacher);
????????Student2?student2?=?(Student2)?student1.clone();
????????System.out.println("拷貝后");
????????System.out.println(student2.getName());
????????System.out.println(student2.getAge());
????????System.out.println(student2.getTeacher().getName());
????????System.out.println(student2.getTeacher().getAge());
????????System.out.println("修改老師的信息后-------------");
????????//?修改老師的信息
????????teacher.setName("Games");
????????System.out.println(student1.getTeacher().getName());
????????System.out.println(student2.getTeacher().getName());
????}
}
class?Teacher?implements?Cloneable?{
????private?String?name;
????private?int?age;
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
????public?int?getAge()?{
????????return?age;
????}
????public?void?setAge(int?age)?{
????????this.age?=?age;
????}
}
class?Student2?implements?Cloneable?{
????private?String?name;
????private?int?age;
????private?Teacher?teacher;
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
????public?int?getAge()?{
????????return?age;
????}
????public?void?setAge(int?age)?{
????????this.age?=?age;
????}
????public?Teacher?getTeacher()?{
????????return?teacher;
????}
????public?void?setTeacher(Teacher?teacher)?{
????????this.teacher?=?teacher;
????}
????public?Object?clone()?throws?CloneNotSupportedException?{
????????Object?object?=?super.clone();
????????return?object;
????}
}
輸出結果:
拷貝后
edgar
18
riemann
27
修改老師的信息后-------------
Games
Games
結果分析:兩個引用student1和student2指向不同的兩個對象,但是兩個引用student1和student2中的兩個teacher引用指向的是同一個對象,所以說明是淺拷貝。

三、深拷貝
(1)、定義
深拷貝是一個整個獨立的對象拷貝,深拷貝會拷貝所有的屬性,并拷貝屬性指向的動態(tài)分配的內(nèi)存。當對象和它所引用的對象一起拷貝時即發(fā)生深拷貝。深拷貝相比于淺拷貝速度較慢并且花銷較大。
簡而言之,深拷貝把要復制的對象所引用的對象都復制了一遍。
往期:100期面試題匯總
(2)、深拷貝實例
package?com.test;
public?class?DeepCopy?{
????public?static?void?main(String[]?args)?throws?CloneNotSupportedException?{
????????Teacher2?teacher?=?new?Teacher2();
????????teacher.setName("riemann");
????????teacher.setAge(27);
????????Student3?student1?=?new?Student3();
????????student1.setName("edgar");
????????student1.setAge(18);
????????student1.setTeacher(teacher);
????????Student3?student2?=?(Student3)?student1.clone();
????????System.out.println("拷貝后");
????????System.out.println(student2.getName());
????????System.out.println(student2.getAge());
????????System.out.println(student2.getTeacher().getName());
????????System.out.println(student2.getTeacher().getAge());
????????System.out.println("修改老師的信息后-------------");
????????//?修改老師的信息
????????teacher.setName("Games");
????????System.out.println(student1.getTeacher().getName());
????????System.out.println(student2.getTeacher().getName());
????}
}
class?Teacher2?implements?Cloneable?{
????private?String?name;
????private?int?age;
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
????public?int?getAge()?{
????????return?age;
????}
????public?void?setAge(int?age)?{
????????this.age?=?age;
????}
????public?Object?clone()?throws?CloneNotSupportedException?{
????????return?super.clone();
????}
}
class?Student3?implements?Cloneable?{
????private?String?name;
????private?int?age;
????private?Teacher2?teacher;
????public?String?getName()?{
????????return?name;
????}
????public?void?setName(String?name)?{
????????this.name?=?name;
????}
????public?int?getAge()?{
????????return?age;
????}
????public?void?setAge(int?age)?{
????????this.age?=?age;
????}
????public?Teacher2?getTeacher()?{
????????return?teacher;
????}
????public?void?setTeacher(Teacher2?teacher)?{
????????this.teacher?=?teacher;
????}
????public?Object?clone()?throws?CloneNotSupportedException?{
????????//?淺復制時:
????????//?Object?object?=?super.clone();
????????//?return?object;
????????//?改為深復制:
????????Student3?student?=?(Student3)?super.clone();
????????//?本來是淺復制,現(xiàn)在將Teacher對象復制一份并重新set進來
????????student.setTeacher((Teacher2)?student.getTeacher().clone());
????????return?student;
????}
}
輸出結果:
拷貝后
edgar
18
riemann
27
修改老師的信息后-------------
Games
riemann
結果分析:
兩個引用student1和student2指向不同的兩個對象,兩個引用student1和student2中的兩個teacher引用指向的是兩個對象,但對teacher對象的修改只能影響student1對象,所以說是深拷貝。

作者:riemann
blog.csdn.net/riemann_/article/details/87217229
?--END--
? 推薦
公眾號ID|javabaiwen
小編微信|619531440
每天分享技術干貨
視頻 | 電子書 | 面試題?|?開發(fā)經(jīng)驗

