连着三次都被大厂面试问到的java面试高频题,一分钟带你彻底搞懂
一、浅拷贝是什么?
浅拷贝会创建一个新的外层对象,但内部的引用类型成员仍然指向原来的对象。
例如:
classAddress{Stringcity;}classPersonimplementsCloneable{Stringname;Addressaddress;@OverrideprotectedPersonclone()throwsCloneNotSupportedException{return(Person)super.clone();}}执行:
Personp2=p1.clone();此时:
p1 != p2 p1.address == p2.address也就是说,Person被复制了,但Address仍然共用。
如果修改:
p2.address.city="上海";那么p1.address.city也会变成“上海”。
浅拷贝常见实现方式
1. Object.clone(),默认是浅拷贝 2. 拷贝构造方法中直接复制引用 3. 手动字段赋值例如:
this.address=other.address;这就是浅拷贝,因为没有创建新的Address。
二、深拷贝是什么?
深拷贝不仅会复制外层对象,还会把内部引用对象也重新创建一份。
例如:
classAddress{Stringcity;publicAddress(Addressother){this.city=other.city;}}classPerson{Stringname;Addressaddress;publicPerson(Personother){this.name=other.name;this.address=newAddress(other.address);}}执行:
Personp2=newPerson(p1);此时:
p1 != p2 p1.address != p2.address修改p2.address不会影响p1.address。
深拷贝常见实现方式
1. 在 clone() 中继续克隆内部对象 2. 深拷贝构造方法 3. 手动逐层创建新对象 4. Java 序列化 5. JSON 序列化例如:
Personcopied=(Person)super.clone();copied.address=this.address.clone();这样内部对象也被重新复制,才是深拷贝。
三、核心区别
| 对比项 | 浅拷贝 | 深拷贝 |
|---|---|---|
| 外层对象是否复制 | 是 | 是 |
| 内部引用对象是否复制 | 否 | 是 |
| 是否共享内部对象 | 是 | 否 |
| 修改内部对象是否互相影响 | 会 | 不会 |
| 实现难度 | 较低 | 较高 |
四、直接赋值不属于拷贝
下面这句:
Personp2=p1;不是浅拷贝,而只是复制了引用。
此时:
p1 和 p2 指向同一个 Person 对象三者区别可以记成:
直接赋值:外层对象共用,内部对象也共用 浅拷贝:外层对象独立,内部对象共用 深拷贝:外层对象独立,内部对象也独立五、实际开发怎么选?
简单对象可以使用浅拷贝。
对象中包含可变引用成员,并且不希望副本修改影响原对象时,应使用深拷贝。
实际项目中更推荐:
简单清晰:拷贝构造方法 性能优先:手动逐层复制 使用方便:JSON 序列化 传统方式:clone()但要注意:
super.clone()默认只实现浅拷贝,不会自动复制内部对象。
六、一句话总结
浅拷贝只复制外层对象,内部引用仍然共享;深拷贝会把内部对象也复制一份,因此新旧对象互不影响。