深复制与浅复制

一、概念

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
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值