Java中的浅拷贝和深拷贝
- 浅拷贝:只拷贝对象本身,而对象中的引用数据类型没有被拷贝的方式。
- 基本类型和String默认会拷贝
- 浅拷贝往往存在一定的风险,因为引用对象的地址拷贝前后一致,所以对象的值很容易被更改,不安全。
- 深拷贝:不仅拷贝对象本身,而且对象中的引用数据类型同样被拷贝的方式。
- 常用的深拷贝的实现方案
- 序列化(serialization)这个对象,再反序列化回来,就可以得到这个新的对象,无非就是序列化的规则需要我们自己来写。
- 继续利用 clone() 方法,既然 clone() 方法,是我们来重写的,实际上我们可以对其内的引用类型的变量,再进行一次 clone()。
浅拷贝示例
private class FatherClass implements Cloneable{
public String name;
public int age;
public ChildClass child;
@Overried
public Object clone(){
try{
//浅拷贝
return super.clone();
} catch ( CloneNotSupportedException ignore){
}
return null;
}
}
复制代码
深拷贝示例
private class FatherClass implements Cloneable{
public String name;
public int age;
public ChildClass child;
@Overried
public Object clone(){
try{
//浅拷贝
FatherClass cloneFather = (FatherClass) super.clone();
cloneFather.child = (ChildClass)this.child.clone();
return cloneFather;
} catch ( CloneNotSupportedException ignore){
}
return null;
}
}
public class ChildClass implements Cloneable{
public String name;
public int age;
@Overried
public Object clone(){
try{
//浅拷贝
return super.clone();
}catch ( CloneNotSupportedException ignore){
}
return null;
}
}
复制代码
序列化示例
public class Student implements Serializable {
private String name;
private int age;
private Teacher teacher;
public Student(String name, int age, Teacher teacher) {
this.name = name;
this.age = age;
this.teacher = teacher;
}
public Student serializableClone() throws IOException, ClassNotFoundException {
Student clone;
ByteArrayOutputStream bo = new ByteArrayOutputStream();
ObjectOutputStream oo = new ObjectOutputStream(bo);
oo.writeObject(this);
ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
ObjectInputStream oi = new ObjectInputStream(bi);
clone = (Student) oi.readObject();
return clone;
}
}
复制代码
原型模式
原型模式介绍
原型二字即可表明该模式有一个样板实例,用户可以从这个样板的对象中复制一个与该对象内部属性一致的对象,也就是我们所说的深拷贝
。
原型模式使用场景
- 资源优化场景
类初始化需要消耗非常多的资源,这个资源包括数据、硬件资源等。
- 性能和安全要求的场景
通过new产生一个对象需要非常繁琐的数据准备或访问权限。
- 一个对象多个修改者的场景
一个对象需要提供给其他对象访问,而且各个调用者可能都需要修改其值时,可以考虑使用原型模式拷贝多个对象供调用者使用。
原型模式使用注意事项
原型模式一般是要实现cloneable接口,并且重写clone方法,但是clone方法并不是Cloneable中的,而是Object中的方法,Cloneable是一个标识接口,它表明这个类的对象是可以拷贝的。如果没有实现Cloneable接口却调用了clone()函数将抛出异常。