前言
Java中的浅拷贝与深拷贝一直是面试中经常问到的热门问题,今天我们一起来复习下,以备面试。
示例先行
举一个日常生活中的例子:
现在我们有一个笔记本,然后我们想要复制它:
浅拷贝:就像只复印了笔记本的封面,里面的内容还是原来那本。如果我们修改复印本封面上的名字,原笔记本不受影响;但是如果我们修改原笔记本里的内容,复印本看到的内容也会变。
深拷贝:就像把整本笔记本从头到尾复印了一遍,包括所有内容。现在我们有两本完全独立的笔记本,修改任何一本都不会影响另一本。
浅拷贝
看到了上面的小栗子,咱们再来介绍的官方一点:
浅拷贝是指创建一个新对象,并且将原始对象的非静态字段复制给这个新对象。如果字段是基本数据类型,那么可以直接复制其值;如果字段是引用类型,则复制的是它的引用地址,而不是引用的对象本身。这就意味着原始对象和拷贝后的对象会共享引用类型的成员变量。
以代码举个例子:
class Address {
String city;
public Address(String city) {
this.city = city;
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 默认的clone是浅拷贝
}
}
public class Main {
public static void main(String[] args) throws Exception {
Address address = new Address("北京");
Person original = new Person("张三", address);
Person copy = (Person) original.clone();
copy.address.city = "上海"; // 修改拷贝对象的address
System.out.println(original.address.city); // 输出的是"上海",因为原对象也被修改了
}
}
在上面这个代码栗子中,copy和original指向同一个对象,就像两个人共享同一本笔记本。
深拷贝
深拷贝是指不仅创建一个新的对象,并且递归地为原始对象中包含的所有引用类型字段创建新的副本。这样做的结果是原始对象和拷贝后的对象不会共享任何引用类型的成员变量。
举个栗子:
class Address implements Cloneable {
String city;
public Address(String city) {
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Person implements Cloneable {
String name;
Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
cloned.address = (Address) address.clone(); // 手动克隆address
return cloned;
}
}
public class Main {
public static void main(String[] args) throws Exception {
Address address = new Address("北京");
Person original = new Person("张三", address);
Person copy = (Person) original.clone();
copy.address.city = "上海"; // 修改拷贝对象的address
System.out.println(original.address.city); // 输出"北京",原对象是不受影响的
}
}
这里clone()方法创建了一个全新的对象,就像复印了一整本笔记本。
浅拷贝与深拷贝对比
特性 | 浅拷贝 | 深拷贝 |
---|---|---|
基本类型字段 | 完全复制 | 完全复制 |
引用类型字段 | 复制引用(指向同一个对象) | 递归复制所有引用对象 |
修改影响 | 修改引用对象会影响原对象 | 完全独立,互不影响 |
实现复杂度 | 简单(Object.clone默认实现) | 复杂(需要手动处理所有引用对象) |
性能 | 快(只复制一层) | 慢(需要递归复制) |
文章小结
浅拷贝:仅复制对象的基本数据类型值以及引用类型的地址,因此原始对象和副本对象可能会共享某些对象。
深拷贝:不仅复制基本数据类型值,还递归地复制所有引用类型的对象,确保原始对象和副本对象完全独立。
本篇文章到这里就结束了,欢迎大家点赞收藏关注,感谢各位小伙伴们的支持!