一、概念
1.浅复制
被复制对象的所有变量都含有与原来的对象相同的值,但是对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
简而言之,浅拷贝仅仅复制所考虑的对象,而不复制它所引用的对象
实例:
public class Product implements Cloneable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Cart implements Cloneable{ private Product product; public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } @Override public Object clone() throws CloneNotSupportedException { Object object = super.clone(); return object; } }
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Product product = new Product(); product.setName("手机"); Cart cart = new Cart(); cart.setProduct(product); Cart cloneCart = (Cart) cart.clone(); System.out.println("changeBefore:"); System.out.println("cart中product的name---" + cart.getProduct().getName()); System.out.println("cloneCart中product的name---" + cloneCart.getProduct().getName()); product.setName("冰箱"); System.out.println("changeAfter:"); System.out.println("cart中product的name---" + cart.getProduct().getName()); System.out.println("cloneCart中product的name---" + cloneCart.getProduct().getName()); System.out.println(cart.getProduct()); System.out.println(cloneCart.getProduct()); } }
打印结果:
changeBefore:
cart中product的name---手机
cloneCart中product的name---手机
changeAfter:
cart中product的name---冰箱
cloneCart中product的name---冰箱
Product@1540e19d
Product@1540e19d
从结果可以看出浅复制的对象和原对象中的引用对象指向的是同一对象,所以当我们修改引用对象的属性时不止原对象会改变,复制对象也会改变。
2.深复制
深拷贝是一个整个独立的对象拷贝,深拷贝会拷贝所有的属性,并拷贝属性指向的动态分配的内存。当对象和它所引用的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
简而言之,深拷贝把要复制的对象所引用的对象都复制一遍,依次递归下去。
实例:
public class Product implements Cloneable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } }
public class Cart implements Cloneable{ private Product product; public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } @Override public Object clone() throws CloneNotSupportedException { Cart cart = (Cart) super.clone(); cart.setProduct((Product)cart.getProduct().clone()); return cart; } }
public class Test { public static void main(String[] args) throws CloneNotSupportedException { Product product = new Product(); product.setName("手机"); Cart cart = new Cart(); cart.setProduct(product); Cart cloneCart = (Cart) cart.clone(); System.out.println("changeBefore:"); System.out.println("cart中product的name---" + cart.getProduct().getName()); System.out.println("cloneCart中product的name---" + cloneCart.getProduct().getName()); product.setName("冰箱"); System.out.println("changeAfter:"); System.out.println("cart中product的name---" + cart.getProduct().getName()); System.out.println("cloneCart中product的name---" + cloneCart.getProduct().getName()); System.out.println(cart.getProduct()); System.out.println(cloneCart.getProduct()); } }
打印结果:
changeBefore:
cart中product的name---手机
cloneCart中product的name---手机
changeAfter:
cart中product的name---冰箱
cloneCart中product的name---手机
Product@1540e19d
Product@677327b6
可以看到此时复制对象与原对象中的引用对象指向了两个不同的对象,而且改变引用对象的属性只对原对象产生了影响。
3:利用序列化实现深拷贝
实例:
public class Product implements Serializable { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
public class Cart implements Serializable { private Product product; public Product getProduct() { return product; } public void setProduct(Product product) { this.product = product; } public Object deepClone() throws Exception { // 序列化 ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos); oos.writeObject(this); // 反序列化 ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(bis); return ois.readObject(); } }
public class Test { public static void main(String[] args) throws Exception { Product product = new Product(); product.setName("手机"); Cart cart = new Cart(); cart.setProduct(product); Cart cloneCart = (Cart) cart.deepClone(); System.out.println("changeBefore:"); System.out.println("cart中product的name---" + cart.getProduct().getName()); System.out.println("cloneCart中product的name---" + cloneCart.getProduct().getName()); product.setName("冰箱"); System.out.println("changeAfter:"); System.out.println("cart中product的name---" + cart.getProduct().getName()); System.out.println("cloneCart中product的name---" + cloneCart.getProduct().getName()); System.out.println(cart.getProduct()); System.out.println(cloneCart.getProduct()); } }
打印结果:
changeBefore:
cart中product的name---手机
cloneCart中product的name---手机
changeAfter:
cart中product的name---冰箱
cloneCart中product的name---手机
Product@330bedb4
Product@2d98a335