克隆是将一个对象复制成另一个完全相同的对象,但内存地址不同,修改原对象的值,克隆出的对象的值不会发生改变。
若某个类的对象需要进行克隆=>(深拷贝、浅拷贝)时,则这个类必须要实现 Cloneable 接口【若果没有实现这个接口,则会抛出
CloneNotSupportedException(克隆不支持异常)】,并且需要在这个类中重写 Object 类中的 clone() 方法。
浅拷贝=>仅仅复制对象本身,基本数据类型进行复制后修改某一对象的属性,不会让其他对象也被修改,而当类中包含其他类的对象
时,仅复制其他类的对象的内存地址,修改一处后会使其他对象都被修改。
例: protected Weapon clone() throws CloneNotSupportedException {
return (Weapon)super.clone();
}
深拷贝(标准)=>利用浅拷贝的方式将其他类的对象向下一层进行复制,然后通过set方法设置给上一层,最终将底层的所有对象全部复制,
修改任何值,都不会对其他属性造成影响。
例:protected Robot clone() throws CloneNotSupportedException {
Robot robot = (Robot)super.clone();
Weapon weapon = robot.getWeapon().clone();
robot.setWeapon(weapon);;
return robot;
}
protected Weapon clone() throws CloneNotSupportedException {
return (Weapon)super.clone();
}
深拷贝(序列化)=>功能和标准的深拷贝相同,但序列化深拷贝是直接将对象序列化成字节流,再将字节流反序列化成为新的对象。
使用这种方法不用实现 Cloneable 接口,但是当前类和其使用到的类都需要实现 Serializable 接口,然后再该类中自定义一个克隆方法(deepClone)。
首先利用 byteArrayOutputStream(字节数组输出流) 和 ObjectOutputStream (对象输出流)将对象序列化成字节流,然后利用
byteArraryInputStream(字节数组输入流)和 ObjectInputStream(对象输入流)将字节流反序列化成为新的对象
例:protected Robot deepClone() throws Exception {
将当前对象“Robot对象”转化为字符流(序列化)
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(this);
将字节流转换成“新的Robot对象”(反序列化)
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
Robot robot = (Robot)ois.readObject();
return robot;
}
标准深拷贝和序列化深拷贝的区别:当一个对象底层包含有若干个对象时,标准的深克隆从最底层开始克隆,效率较低。
而序列化深拷贝直接将最外层的对象整体的序列化,再利用反序列化克隆出一个新的对象,效率较高。