什么是克隆方法?
创建并返回此对象的一个副本–按照原对象,创建一个新的对象(复制原对象的内容)
已经存在new关键字和反射技术都可以创建对象,为什么还需要一个Object的clone方法呢?
new和反射创建内容一样的对象,需要不断的new和set,较麻烦
使用clone方法创建对象
1.在需要调用clone方法的对象上添加实现Cloneable接口
2.复写clone方法,在自己的clone方法中调用父类的clone方法,将返回值类型强制转成本类型,将当前clone方法的修饰符改成public
3.在测试中调用对象的clone方法
浅表复制
1.克隆对象是一个新的对象
2.克隆对象的成员变量与原对象的成员变量是同一个数据(底层哈希值一致)
浅表复制的弊端
因为浅表复制克隆的对象的成员变量是对同一对象的引用,如果我们操作其中一个对象的成员变量的内容,就会导致,所有克隆对象的成员内容都发生改变。
clone方法默认的复制操作是浅表复制,浅表复制存在弊端–仅仅创建新的对象,对象的成员内容底层哈希值是一致的。因此,不管是原对象还是克隆对象,只有其中一个修改了成员的值,就会影响所有的原对象和克隆对象。
深层复制
执行克隆时,不仅克隆对象是新的对象,克隆对象中的成员变量,也要求是一个新的对象
1.修改Children类实现Cloneable接口
2.修改Children类重写clone方法
3.修改Person类重写clone方法,在clone方法中调用Children的clone方法
public Person3 clone() throws CloneNotSupportedException {
Person3 clone=(Person3)super.clone();
clone.setChild(child.clone());
return clone;
}
深层复制的弊端
如果成员变量特别多,需要修改多个类的源码
重复实现Cloneable接口
重复实现clone方法
重复改写Person类的clone方法
使用IO流的方式进行复制操作(深层复制,解决重复修改源代码的问题)
1.创建ByteArrayOutputStream,将数据转换成字节
2.创建ObjectOutputStream,关联ByteArrayOutputStream
3.使用ObjectOutputStream的writeObject,读取要复制的对象
4.使用ByteArrayInputStream读取ByteArrayOutputStream的转换的对象字节数据
5.创建ObjectInputStream读取对象字节数据,创建新的对象
使用IO改写Person的clone方法
1.克隆涉及的所有类实现Serializable
2.修改Person类的clone方法,使用IO复制对象