连着三次都被大厂面试问到的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()

默认只实现浅拷贝,不会自动复制内部对象。


六、一句话总结

浅拷贝只复制外层对象,内部引用仍然共享;深拷贝会把内部对象也复制一份,因此新旧对象互不影响。