"浅拷贝和深拷贝的区别"是一个经典问题。这个问题不仅考察你对对象复制的理解,还涉及到内存管理、引用机制和对象序列化等核心概念。本文将深入浅出地讲解这两个概念。

在Java中,当我们说"拷贝"一个对象时,我们指的是创建一个与原对象状态相同的新对象。但这里的"状态相同"有不同的理解方式,这就引出了浅拷贝和深拷贝的概念。
浅拷贝是指创建一个新对象,这个新对象有着原始对象属性值的一份精确拷贝。如果属性是基本数据类型,拷贝的就是基本数据类型的值;如果属性是引用类型,拷贝的就是内存地址。
class Address {
String city;
public Address(String city) {
this.city = city;
}
}
class Person implements Cloneable {
String name;
int age;
Address address;
public Person(String name, int age, Address address) {
this.name = name;
this.age = age;
this.address = address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone(); // 这就是浅拷贝
}
}
// 使用示例
Address addr = new Address("北京");
Person p1 = new Person("张三", 25, addr);
Person p2 = (Person) p1.clone();
// 修改p2的引用类型属性
p2.address.city = "上海";
System.out.println(p1.address.city); // 输出:上海
System.out.println(p2.address.city); // 输出:上海可以看到,修改p2的address.city也影响了p1,因为它们共享同一个Address对象。
深拷贝是指创建一个新对象,不仅复制原始对象的基本数据类型,还会为引用类型的成员变量创建新的实例。
@Override
protected Object clone() throws CloneNotSupportedException {
Person cloned = (Person) super.clone();
// 对引用类型进行深拷贝
cloned.address = new Address(this.address.city);
return cloned;
}public Person deepCopy() {
try {
// 将对象序列化到字节流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 从字节流反序列化创建新对象
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (Person) ois.readObject();
} catch (Exception e) {
throw new RuntimeException(e);
}
}注意:使用序列化方式需要实现Serializable接口。
回答要点:
回答要点:
回答要点:
回答要点:
回答要点:
浅拷贝和深拷贝的选择本质上是性能与安全性的权衡。不仅要能说出两者的区别,还要能分析具体场景下的选择依据。没有绝对的好坏,只有是否适合当前需求。