面试题答案
一键面试1. 实现A类的深拷贝
假设类结构如下:
class C implements Cloneable {
private int value;
public C(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
protected C clone() throws CloneNotSupportedException {
return (C) super.clone();
}
}
class B implements Cloneable {
private C c;
public B(C c) {
this.c = c;
}
public C getC() {
return c;
}
@Override
protected B clone() throws CloneNotSupportedException {
C clonedC = c.clone();
B clonedB = (B) super.clone();
clonedB.c = clonedC;
return clonedB;
}
}
class A implements Cloneable {
private B b;
public A(B b) {
this.b = b;
}
public B getB() {
return b;
}
@Override
protected A clone() throws CloneNotSupportedException {
B clonedB = b.clone();
A clonedA = (A) super.clone();
clonedA.b = clonedB;
return clonedA;
}
}
在上述代码中,A
类包含B
类对象,B
类包含C
类对象。每个类都实现了Cloneable
接口并重写了clone
方法。在A
类的clone
方法中,先克隆B
对象,再克隆A
对象本身,并将克隆的B
对象赋值给克隆的A
对象,以此实现深拷贝。
2. 性能优化
- 缓存已克隆对象:可以使用一个
Map
来缓存已经克隆过的对象,避免重复克隆。例如:
import java.util.HashMap;
import java.util.Map;
class C implements Cloneable {
private int value;
public C(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
protected C clone(Map<Object, Object> clonedMap) throws CloneNotSupportedException {
if (clonedMap.containsKey(this)) {
return (C) clonedMap.get(this);
}
C clonedC = (C) super.clone();
clonedMap.put(this, clonedC);
return clonedC;
}
}
class B implements Cloneable {
private C c;
public B(C c) {
this.c = c;
}
public C getC() {
return c;
}
@Override
protected B clone(Map<Object, Object> clonedMap) throws CloneNotSupportedException {
if (clonedMap.containsKey(this)) {
return (B) clonedMap.get(this);
}
C clonedC = c.clone(clonedMap);
B clonedB = (B) super.clone();
clonedB.c = clonedC;
clonedMap.put(this, clonedB);
return clonedB;
}
}
class A implements Cloneable {
private B b;
public A(B b) {
this.b = b;
}
public B getB() {
return b;
}
@Override
protected A clone() throws CloneNotSupportedException {
Map<Object, Object> clonedMap = new HashMap<>();
B clonedB = b.clone(clonedMap);
A clonedA = (A) super.clone();
clonedA.b = clonedB;
return clonedA;
}
}
- 使用序列化和反序列化:如果对象结构支持序列化,可以使用
ObjectOutputStream
和ObjectInputStream
进行深拷贝。这种方法适用于对象结构简单且所有类都实现了Serializable
接口的情况。但它的性能开销较大,不适合频繁调用。
3. 可能遇到的问题及解决方案
- 循环引用问题:如果对象结构中存在循环引用,例如
A
类包含B
类对象,B
类又包含A
类对象,普通的克隆方法会导致无限递归。解决方案是使用上述提到的缓存已克隆对象的方法,在克隆过程中判断对象是否已被克隆,避免重复克隆。 - 未实现Cloneable接口:如果某个嵌套类没有实现
Cloneable
接口,调用clone
方法会抛出CloneNotSupportedException
。需要确保所有涉及到的类都实现Cloneable
接口。 - 静态成员和不可变对象:静态成员不会被克隆,因为它们属于类级别而非对象级别。对于不可变对象,无需克隆,直接使用原对象即可,因为其内容不可改变,不会影响深拷贝的语义。