面试题答案
一键面试浅拷贝的实现
- 实现
Cloneable
接口:在Java中,要实现浅拷贝,类需要实现java.lang.Cloneable
接口,该接口是一个标记接口,没有任何方法。 - 重写
clone()
方法:Object
类中有一个protected
修饰的clone()
方法,需要在自定义类中重写该方法,并将其访问修饰符改为public
。
以下是一个包含基本数据类型和对象引用的自定义类实现浅拷贝的示例:
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 int age;
private String name;
private Address address;
public Person(int age, String name, Address address) {
this.age = age;
this.name = name;
this.address = address;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public Person clone() throws CloneNotSupportedException {
return (Person) super.clone();
}
}
浅拷贝在处理对象引用时的局限性
浅拷贝对于包含对象引用的成员变量,只是复制了引用地址,而不是创建新的对象。这意味着原对象和拷贝对象的相应对象引用指向同一个实际对象。
例如,继续使用上面的Person
类:
public class Main {
public static void main(String[] args) {
Address address = new Address("Beijing");
Person person1 = new Person(30, "Alice", address);
try {
Person person2 = person1.clone();
// 修改person2的基本数据类型字段
person2.setAge(31);
// 修改person2的对象引用字段
person2.getAddress().setCity("Shanghai");
System.out.println("person1 age: " + person1.getAge());
System.out.println("person1 city: " + person1.getAddress().getCity());
System.out.println("person2 age: " + person2.getAge());
System.out.println("person2 city: " + person2.getAddress().getCity());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
输出结果为:
person1 age: 30
person1 city: Shanghai
person2 age: 31
person2 city: Shanghai
可以看到,修改person2
的address
对象的city
属性,person1
的address
对象的city
属性也发生了改变,因为它们共享同一个Address
对象的引用。这就是浅拷贝在处理对象引用时的局限性,如果需要避免这种情况,应该使用深拷贝,即对对象引用的成员变量也进行递归的拷贝。