准备工作
@Data
@AllArgsConstructor
public class Product implements Cloneable{
private String name;
private int stock;
private double price;
@Override
protected Product clone() throws CloneNotSupportedException {
return (Product)super.clone();
}
}
@Data
@AllArgsConstructor
public class PromotionRule implements Cloneable{
private String type;
private int discount;
private Product product;
@Override
protected PromotionRule clone() throws CloneNotSupportedException {
return (PromotionRule)super.clone();
}
}
使用原生的clone方法
public class DeepClone {
public static void main(String[] args) {
// 产品
Product iphone = new Product("Iphone",10 , 100000);
// 促销规则
PromotionRule promotionRule = new PromotionRule("dker45", 10, iphone);
PromotionRule promotionRule2 = null;
try {
promotionRule2 = promotionRule.clone();
promotionRule2.getProduct().setStock(20);
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
System.out.println(promotionRule); // stock=20
System.out.println(promotionRule2); // stock=20
}
}
从输出的结果可以看出clone()方法实现的是浅拷贝
递归克隆
@Data
@AllArgsConstructor
public class PromotionRule implements Cloneable {
private String type;
private int discount;
private Product product;
@Override
protected PromotionRule clone() throws CloneNotSupportedException {
PromotionRule promotionRule = (PromotionRule) super.clone();
if (null != product) {
// 调用对象类型的clone()实现深拷贝
promotionRule.setProduct(product.clone());
}
return promotionRule;
}
}
修改完成后重新调用main方法发现可以实现深拷贝了。
递归克隆的缺点在于,如果对象中包含的对象太多、需要依次克隆。
递归克隆的思路在装饰者模式中也有运用。
使用序列化克隆
@Data
@AllArgsConstructor
public class Product implements Cloneable, Serializable {
private String name;
private int stock;
private double price;
@Override
protected Product clone() throws CloneNotSupportedException {
return (Product) super.clone();
}
}
@Data
@AllArgsConstructor
public class PromotionRule implements Cloneable, Serializable {
private String type;
private int discount;
private Product product;
@Override
protected PromotionRule clone() throws CloneNotSupportedException {
PromotionRule promotionRule = (PromotionRule) super.clone();
if (null != product) {
promotionRule.setProduct(product.clone());
}
return promotionRule;
}
}
public class DeepClone {
public static void main(String[] args) {
// 产品
Product iphone = new Product("Iphone",10 , 100000);
// 促销规则
PromotionRule promotionRule = new PromotionRule("dker45", 10, iphone);
PromotionRule promotionRule2 = null;
try {
promotionRule2 = (PromotionRule) doDeepCloneByStream(promotionRule);
promotionRule2.getProduct().setStock(20);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(promotionRule); // stock=20
System.out.println(promotionRule2); // stock=20
// 从输出的结果可以看出clone()方法实现的是浅拷贝
}
public static Object doDeepCloneByStream(Object obj) {
ObjectOutputStream oos = null;
Object res = null;
try {
// 1.将对象输出到字节数组中
ByteArrayOutputStream out = new ByteArrayOutputStream();
oos = new ObjectOutputStream(out);
oos.writeObject(obj);
byte[] bytes = out.toByteArray();
// 2.将字节数组读到对象中
ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
res = ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return res;
}
}