面试题答案
一键面试- 使用序列化和反序列化实现深拷贝:
- 首先,确保需要拷贝的类实现
Serializable
接口。 - 示例代码如下:
- 首先,确保需要拷贝的类实现
import java.io.*;
class DeepCopyExample {
public static <T> T deepCopy(T obj) throws IOException, ClassNotFoundException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(obj);
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return (T) ois.readObject();
}
}
- 这种方法的优点是实现简单,能处理复杂对象图和循环引用。缺点是要求所有类实现
Serializable
接口,并且性能相对较低,因为涉及到字节流的读写。
- 手动递归实现深拷贝:
- 以一个简单的对象层次结构为例,假设有
A
类,A
类包含B
类的对象和一个List<String>
。
- 以一个简单的对象层次结构为例,假设有
import java.util.ArrayList;
import java.util.List;
class B {
private String data;
public B(String data) {
this.data = data;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
// 深拷贝方法
public B deepCopy() {
return new B(data);
}
}
class A {
private B b;
private List<String> list;
public A(B b, List<String> list) {
this.b = b;
this.list = list;
}
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public List<String> getList() {
return list;
}
public void setList(List<String> list) {
this.list = list;
}
// 深拷贝方法
public A deepCopy() {
B newB = b.deepCopy();
List<String> newList = new ArrayList<>();
newList.addAll(list);
return new A(newB, newList);
}
}
- 手动递归实现深拷贝需要在每个类中编写深拷贝方法,优点是性能相对较好,不需要实现
Serializable
接口。缺点是实现复杂,需要手动处理每个层次的对象拷贝,并且处理循环引用需要额外的逻辑,例如可以使用一个Map
来记录已经拷贝过的对象。例如:
import java.util.HashMap;
import java.util.Map;
class C {
private D d;
private Map<Object, Object> visited = new HashMap<>();
public C(D d) {
this.d = d;
}
public D getD() {
return d;
}
public void setD(D d) {
this.d = d;
}
public C deepCopy() {
if (visited.containsKey(this)) {
return (C) visited.get(this);
}
D newD = d.deepCopy(visited);
C newC = new C(newD);
visited.put(this, newC);
return newC;
}
}
class D {
private String value;
public D(String value) {
this.value = value;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public D deepCopy(Map<Object, Object> visited) {
if (visited.containsKey(this)) {
return (D) visited.get(this);
}
D newD = new D(value);
visited.put(this, newD);
return newD;
}
}
这样通过Map
记录已经拷贝过的对象,在拷贝时如果发现对象已经拷贝过则直接返回已拷贝的对象,从而避免循环引用问题。