面试题答案
一键面试深拷贝和浅拷贝的区别
- 浅拷贝:
- 浅拷贝会创建一个新对象,新对象的基本数据类型字段值与原对象相同,对于对象引用类型字段,新对象和原对象的该字段引用同一个对象。
- 也就是说,如果原对象中某个引用类型字段指向的对象发生改变,浅拷贝后的对象中该字段指向的对象也会改变。
- 深拷贝:
- 深拷贝不仅会创建一个新对象,新对象的基本数据类型字段值与原对象相同,而且对于对象引用类型字段,会递归地复制其引用的对象,即新对象和原对象的引用类型字段指向不同的对象。
- 这样,原对象中某个引用类型字段指向的对象发生改变,不会影响深拷贝后的对象中该字段指向的对象。
浅拷贝实现示例
class Address {
private String city;
public Address(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
class Person implements Cloneable {
private String name;
private Address address;
public Person(String name, Address address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public Address getAddress() {
return address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class ShallowCopyExample {
public static void main(String[] args) {
try {
Address address = new Address("Beijing");
Person person1 = new Person("Tom", address);
Person person2 = (Person) person1.clone();
System.out.println("Before change:");
System.out.println("Person1 address city: " + person1.getAddress().getCity());
System.out.println("Person2 address city: " + person2.getAddress().getCity());
person1.getAddress().setCity("Shanghai");
System.out.println("After change:");
System.out.println("Person1 address city: " + person1.getAddress().getCity());
System.out.println("Person2 address city: " + person2.getAddress().getCity());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
在上述示例中,Person
类实现了Cloneable
接口并重写了clone
方法,这里只是调用了super.clone()
实现浅拷贝。当修改person1
中address
对象的city
属性时,person2
中address
对象的city
属性也会改变。
深拷贝实现示例
class AddressDeepCopy implements Cloneable {
private String city;
public AddressDeepCopy(String city) {
this.city = city;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class PersonDeepCopy implements Cloneable {
private String name;
private AddressDeepCopy address;
public PersonDeepCopy(String name, AddressDeepCopy address) {
this.name = name;
this.address = address;
}
public String getName() {
return name;
}
public AddressDeepCopy getAddress() {
return address;
}
@Override
protected Object clone() throws CloneNotSupportedException {
PersonDeepCopy cloned = (PersonDeepCopy) super.clone();
cloned.address = (AddressDeepCopy) address.clone();
return cloned;
}
}
public class DeepCopyExample {
public static void main(String[] args) {
try {
AddressDeepCopy address = new AddressDeepCopy("Beijing");
PersonDeepCopy person1 = new PersonDeepCopy("Tom", address);
PersonDeepCopy person2 = (PersonDeepCopy) person1.clone();
System.out.println("Before change:");
System.out.println("Person1 address city: " + person1.getAddress().getCity());
System.out.println("Person2 address city: " + person2.getAddress().getCity());
person1.getAddress().setCity("Shanghai");
System.out.println("After change:");
System.out.println("Person1 address city: " + person1.getAddress().getCity());
System.out.println("Person2 address city: " + person2.getAddress().getCity());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
在这个深拷贝示例中,PersonDeepCopy
类的clone
方法不仅调用super.clone()
克隆自身,还对address
对象进行了克隆,使得person1
和person2
的address
对象是不同的,修改person1
中address
对象的city
属性,不会影响person2
中address
对象的city
属性。