Java 浅拷贝和深拷贝

8 篇文章 0 订阅

在Java中, 类可以通过实现 Cloneable 接口来实现.

但是由此方法拷贝的对象是浅拷贝. 具体地说, 对于对象内部的基本类型是深拷贝, 而引用类型是浅拷贝.

查看以下代码: (省略constructor, getter, setter, toString…)

package prototype;

import java.io.Serializable;

public class Bar implements Serializable {
    private String name;
}
 package prototype;
 
 import java.io.*;
 
 public class Prototype implements Cloneable, Serializable {
     private long id;
     private Bar bar;
 
     @Override
     public Prototype clone() {
         try {
             return (Prototype) super.clone();
         } catch (CloneNotSupportedException e) {
             e.printStackTrace();
             return null;
         }
     }
 
     public Prototype deepClone() throws Exception {
         var baos = new ByteArrayOutputStream();
         var oos  = new ObjectOutputStream(baos);
         oos.writeObject(this);
         var bais = new ByteArrayInputStream(baos.toByteArray());
         var ois  = new ObjectInputStream(bais);
         return (Prototype) ois.readObject();
     }
 }
 package prototype;
 
 public class Client {
     public static void main(String[] args) throws Exception {
         Prototype prototype = new Prototype();
         prototype.setBar(new Bar("bar"));
         prototype.setId(3);
 
         //浅拷贝
         Prototype prototype1 = prototype.clone();
 
         System.out.println("=== if any of the following varies, then it is shallow clone ===");
 
         //基本类型是深拷贝
         prototype1.setId(2);
         System.out.println("the old id is 3, and now it is " + prototype.getId());
         //引用类型是浅拷贝
         prototype1.getBar().setName("newbar");
         System.out.println("the old bar is {bar}, and now it is {" + prototype.getBar().getName()+"} <==");
 
         //序列化来实现深拷贝
         //Prototype 类以及 Bar 类都要实现 Serializable 接口
         prototype.getBar().setName("bar"); //恢复旧名字
         Prototype prototype2 = prototype.deepClone();
         prototype2.getBar().setName("newbar");
         System.out.println("the old bar is {bar}, and now it is {"+prototype.getBar().getName()+"}");
     }
 }

以下是输出结果

=== if any of the following varies, then it is shallow clone ===
the old id is 3, and now it is 3
the old bar is {bar}, and now it is {newbar} <==
the old bar is {bar}, and now it is {bar}

可以观察到: 进行浅拷贝后, 若通过新的对象改变对象内部的引用类型对象, 原有对象的内部的引用对象也会做出相同的改变. 之所以会发生这样的事情, 是因为此时两个对象内部包含的对象是同一个.

用序列化可以实现深拷贝.

在上面的代码中, Prototype类和Bar类都实现了了Serializable接口.

使用Prototype类中的deepClone方法得到的对象是深拷贝对象.

如果类的结构不至于太复杂, 对于引用型对象来说, 可以通过使用 new 关键字来实现深拷贝.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值