Java中实现对象拷贝通常有两种方式:浅拷贝和深拷贝。浅拷贝只复制原对象中所有基本数据类型的值和引用类型变量的地址,而深拷贝则是在堆中重新开辟空间,将原对象的所有属性都复制到新的对象中去,新的对象与原始对象没有任何关联。本文将讲解Java中实现深拷贝的两种方式:clone()和Serialized。
使用clone()方法实现深拷贝
Java中Object类提供了一个clone()方法,允许对象从内存中进行复制,并将复制后的新对象返回。注意,使用该方法进行克隆需要确保所复制的类实现了Cloneable接口,并重写了Object类中的clone()方法。否则,在调用clone()方法时,编译器将会抛出CloneNotSupportedException异常。
下面是一个示例代码:
public class Person implements Cloneable {
private String name;
private List<String> hobbies;
public Person(String name, List<String> hobbies) {
this.name = name;
this.hobbies = hobbies;
}
@Override
public Object clone() throws CloneNotSupportedException {
//浅拷贝
Person copy = (Person) super.clone();
//深拷贝
copy.hobbies = new ArrayList<>(this.hobbies);
return copy;
}
}
上述代码中,Person类实现了Cloneable接口,并重写了clone()方法。在clone()方法中,使用super.clone()进行浅拷贝,再使用new创建新的List对象对hobbies进行深拷贝,确保返回的新对象与原始对象没有任何关联。
下面是一个使用clone()方法实现深拷贝的测试例子:
public class CloneTest {
public static void main(String[] args) throws CloneNotSupportedException {
List<String> hobbies = new ArrayList<>();
hobbies.add("coding");
Person person1 = new Person("Tom", hobbies);
Person person2 = (Person)person1.clone();
System.out.println(person1 == person2); // false
System.out.println(person1.getHobbies() == person2.getHobbies()); // false
}
}
使用clone()方法进行深拷贝后,测试代码输出__false, false__,说明person1与person2是两个不同的对象,同时person2的hobbies属性也是一个新的List对象,与person1的hobbies属性没有任何关联。
使用Serialized实现深拷贝
Java中的Serialized机制能够将对象的状态保存到文件中,也可以在网络上将对象的状态传输给其他计算机。被Serialized处理过的对象能够进行深拷贝。
下面是一个示例代码:
public class Person implements Serializable {
private String name;
private List<String> hobbies;
public Person(String name, List<String> hobbies) {
this.name = name;
this.hobbies = hobbies;
}
public List<String> getHobbies() {
return hobbies;
}
public String getName() {
return name;
}
public void setHobbies(List<String> hobbies) {
this.hobbies = hobbies;
}
public void setName(String name) {
this.name = name;
}
public Object deepClone() throws IOException, ClassNotFoundException {
// 复制到流中
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
// 从流中读回
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
return ois.readObject();
}
}
上述示例代码中,Person实现了Serializable接口,同时实现了一个deepClone()方法进行深拷贝。在deepClone()方法中,将对象复制到输出流中,再从输入流中读取并创建新的对象。使用该方法能够完全复制原始对象,确保返回的新对象与原始对象没有任何关联。但同时也需要注意,要求Person类中所有成员变量都是Serializable的。
下面是一个使用Serialized实现深拷贝的测试例子:
public class SerializedTest {
public static void main(String[] args) throws IOException, ClassNotFoundException {
List<String> hobbies = new ArrayList<>();
hobbies.add("reading");
Person person1 = new Person("Lucy", hobbies);
Person person2 = (Person) person1.deepClone();
System.out.println(person1 == person2); // false
System.out.println(person1.getHobbies() == person2.getHobbies()); // false
}
}
使用Serialized机制实现深拷贝后,测试代码输出__false, false__,说明person1与person2是两个不同的对象,同时person2的hobbies属性也是一个新的List对象,与person1的hobbies属性没有任何关联。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:浅谈Java中实现深拷贝的两种方式—clone() & Serialized - Python技术站