原先的方式
Sheep sheep = new Sheep("tom", 1, "white");
Sheep sheep1 = new Sheep(sheep.getName(), sheep.getAge(), sheep.getColor());
System.out.println(sheep1);
总是要重新初始化对象, 而不是动态地获得对象运行时的状态, 不够灵活, 如果中途添加了属性也要改代码才行。
改进 使用clone()方法, 但必须由被clone类实现Cloneable接口。 => Prototype Pattern
(浅拷贝)
public class Sheep implements Cloneable{
@Override
protected Object clone(){
Sheep sheep = null;
try{
sheep = (Sheep) super.clone(); // 默认是浅拷贝
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return sheep;
}
}
// NewClient.java
public class NewClient {
public static void main(String[] args) {
Sheep sheep = new Sheep("Tom", 1, "White");
sheep.friend = new Sheep("Jerry", 2, "Black"); // shadow copy
Sheep sheep1 = (Sheep) sheep.clone();
System.out.println(sheep1);
System.out.println(sheep.hashCode()); //1360875712
System.out.println(sheep1.hashCode()); //1625635731
System.out.println(sheep.friend.hashCode()); // 1580066828
System.out.println(sheep1.friend.hashCode()); //1580066828
}
}
深拷贝 (方式一:重写clone()方法 方式二:通过对象序列化)
public class DeepPrototype implements Serializable, Cloneable {
public String name;
public Goat goat;
public DeepPrototype() {
}
// let's do the deep copy
//method 1 : overwrite clone()
@Override
protected Object clone() {
DeepPrototype deepPrototype = null;
try {
deepPrototype =(DeepPrototype) super.clone();
deepPrototype.goat = (Goat)goat.clone();
}catch (CloneNotSupportedException e){
e.printStackTrace();
}
return deepPrototype;
}
}
深拷贝 (通过对象序列化 RECOMMENDED)
public Object serializableClone(){
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
// Serialize
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this); // 将当前对象以对象流的方式输出
//Unserialize
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
DeepPrototype deepPrototype = (DeepPrototype) ois.readObject();
return deepPrototype;
}catch (Exception e){
e.printStackTrace();
}finally {
try {
ois.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bis.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
oos.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}