zoukankan      html  css  js  c++  java
  • java基础-浅复制与深复制的理解

    浅复制与深复制在很多编程语言中都有出现,那么什么是浅复制,什么是深复制呢?

    要区分浅复制与深复制,首先我们要明确什么是复制,怎样才算是复制。复制的例子在生活中也随处可见,如复印一份文档,复制一段文字等。我们可以发现,复制操作后可以得到两份相同的东西,即复制由一变为二了。下面来看一个例子:

    public class User{
    
         private int age;
    
    
         public int getAge(){
    
              return age;
    
         }
    
    }
    
    User user1 = new User();
    
    User user2 = user1;

    上面把user2 = user1属于复制吗?显然,这种操作不属于复制,因为user2=user1仅仅是把user1的引用赋值给user2,此时user1与user2指向内存中同一个对象,所以没有一变成二。在Java中的复制需要得到两个相同的对象,而不是指两个相同的引用。

    如果要得到一个真正的复制对象,需要自行实现clone()方法,clone()方法存在于Object类中,默认被所有的类继承,方法签名如下:

    protected native Object clone() throws CloneNotSupportedException;

    由于clone()方法是用protected修饰的,不能在类外被调用,所以我们如果要复制一个对象,就需要在类中覆盖clone()方法,并把修饰符升级为public,而且被复制的类需要实现Cloneable接口,否则调用clone()方法时会抛出CloneNotSupportedException异常。

    public class User implements Cloneable{
    
         public User(int age){
    
              this.age = age;
    
         }
    
         private int age;
    
         public int getAge(){
    
              return age;
    
         }
    
         public Object clone() {
    
              User user = null;
    
              try{
    
                   user = super.clone();
    
              }catch(Exception e){
    
              }
    
              return user;
    
         }
    
    }
    
    User usr1 = new User(12);
    
    User usr2 = usr1.clone();
    
    System.out.println(usr1==usr2); 
    
    System.out.println(usr1.getAge()+", "+ usr2.getAge());
    
    ######结果
    
    false
    
    12, 12

    说明clone方法得到了两个对象,且变量相同。上面的例子说明的仅仅是浅复制的情况,下面再来看一个例子:

    public class Phone{
    
         private String name;
    
         public Phone(String name){
    
              this.name = name;
    
         }
    
         public void setName(String name){
    
              this.name = name;
    
         }
    
         public String getName(){
    
              return this.name;
    
         }
    
    }
    
    public class User implements Cloneable{
    
         public User(int age){
    
              this.age = age;
    
              this.phone = new Phone("华为");
    
         }
    
         private int age;
    
         public Phone phone;
    
         public int getAge(){
    
              return age;
    
         }
    
         public Object clone() {
    
              User user = null;
    
              try{
    
                   user = super.clone();
    
              }catch(Exception e){
    
              }
    
              return user;
    
         }
    
    }

    上面代码定义了User类和Phone类,其中User类有一个Phone类的变量,下面调用这两个类:

    User usr1 = new User(12);
    
    User usr2 = usr1.clone();
    
    System.out.println(usr1==usr2);
    
    System.out.println(usr1.getAge()+", "+ usr2.getAge());
    
    System.out.println(usr1.phone.getName()+", "+ usr2.phone.getName());
    
    usr1.phone.setName("小米");
    
    System.out.println(usr1.phone.getName()+", "+ usr2.phone.getName());
    
    ###结果
    
    false
    
    12, 12
    
    华为, 华为
    
    小米, 小米

    有没有发现一些问题了?修改usr1的变量phone的name的值,修改为“小米”,但是usr2的变量phone的name的值也变为“小米”了。这说明了usr1与usr2的phone变量引用的Phone对象是同一个的,上面的这种复制就是浅复制,浅复制没有复制引用类型的变量。

    为了达到深复制,我们需要把类中的引用类型也变成可复制化,即实现Cloneable接口,如下:

    public class Phone implements Cloneable{
    
         private String name;
    
         public Phone(String name){
    
              this.name = name;
    
         }
    
         public void setName(String name){
    
              this.name = name;
    
         }
    
         public String getName(){
    
              return this.name;
    
         }
    
         public Object clone(){
    
              Phone phone = null;
    
              try{
    
                   phone = super.clone();
    
              }catch(Exception e){
    
              }
    
              return phone;
    
         }
    
    }
    
    public class User implements Cloneable{
    
         public User(int age){
    
              this.age = age;
    
              this.phone = new Phone("华为");
    
         }
    
         private int age;
    
         public Phone phone;
    
         public int getAge(){
    
              return age;
    
         }
    
         public Object clone() {
    
              User user = null;
    
              try{
    
                   user = super.clone();
    
              }catch(Exception e){
    
              }
    
              user.phone = (Phone)phone.clone();
    
              return user;
    
         }
    
    }

    由上可以总结,浅复制会把基本数据类型的变量都复制一份,对于引用类型变量只是仅仅对引用进行复制,没有对引用的内存对象进行复制;而深复制会把对象复制一份,也会把对象的引用变量指向的对象复制一份,深复制复制更加彻底。

    文章同步发布在朗度云网站上,传输门:

    http://www.wolfbe.com/detail/201608/271.html

  • 相关阅读:
    HashMap put原理详解(基于jdk1.8)
    适合 C++ 新手学习的开源项目——在 GitHub 学编程
    连续肝了好几天,终于把Java面试必备最重要的基础知识【Java集合】知识点总结整理出来了。
    「精选」史上最全Java工程师面试题汇总,没有之一,不接受反驳!
    想拿到10k-40k的offer,这些技能必不可少!作为程序员的你了解吗?
    QuickBI助你成为分析师-数据建模(一)
    Java Web整合开发(36) -- Web Service框架XFire
    查找
    CentOS7下RabbitMQ服务安装配置
    php rabbitmq操作类及生产者和消费者实例代码 转
  • 原文地址:https://www.cnblogs.com/beyondfengyu/p/5769433.html
Copyright © 2011-2022 走看看