深拷贝和浅拷贝的理解与应用

对象拷贝就是将一个对象的属性拷贝到另一个有着相同类型的对象中去。java中有两种类型的对象拷贝:深拷贝、浅拷贝。

假如我们要复制一对基本数据类型变量到另外一个具有相同的类型的基本变量时,我们一般会这样做

  int sourceValue=10;
  int targetValue=sourceValue;

上面只是一个例子,除了int类型,其中七种原始数据类型(boolean,char,byte,short,float,double.long)同样适用于上述该类情况。

如果要复制一个对象,情况就不是这么简单了。

正如我们所知:java存储变量的区域为栈,存放对象的位置为堆,例如以下的代码表示
 

public static void main(String[] args){

    User user =new User();
    
}

user所在的内存图

深拷贝和浅拷贝的理解与应用_第1张图片

继续上面的user,如下的程序应该是很多人都是这样干的吧

public static void main(String[] args){
    // 定义一个User对象
    User user =new User();
    // 设置值
    user.setName("测试深拷贝和浅拷贝");
    // 将user对象复制给tempUser 对象
    User tempUser =user;
    

    System.out.println(user.equals(tempUser));

    user.setName("抛弃深拷贝和浅拷贝");

    System.out.println(tempUser.getName());
    
}

输入结果如下

在看如下来代码

public static void main(String[] args){

   // 定义一个User对象
      User user =new User();
      // 设置值
      user.setName("测试深拷贝和浅拷贝");
      // 将user对象复制给tempUser 对象
      User tempUser = (User) user.clone();


      System.out.println(user.equals(tempUser));

      user.setName("抛弃深拷贝和浅拷贝");

      System.out.println(tempUser.getName());
}

输入结果竟然如下:

其实这是很正常的,解决这异常的办法是让User类来实现Cloneable接口,Cloneable接口里面没有一个方法,

/*
 * Copyright (c) 1995, 2004, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package java.lang;

/**
 * A class implements the Cloneable interface to
 * indicate to the {@link java.lang.Object#clone()} method that it
 * is legal for that method to make a
 * field-for-field copy of instances of that class.
 * 

* Invoking Object's clone method on an instance that does not implement the * Cloneable interface results in the exception * CloneNotSupportedException being thrown. *

* By convention, classes that implement this interface should override * Object.clone (which is protected) with a public method. * See {@link java.lang.Object#clone()} for details on overriding this * method. *

* Note that this interface does not contain the clone method. * Therefore, it is not possible to clone an object merely by virtue of the * fact that it implements this interface. Even if the clone method is invoked * reflectively, there is no guarantee that it will succeed. * * @author unascribed * @see java.lang.CloneNotSupportedException * @see java.lang.Object#clone() * @since JDK1.0 */ public interface Cloneable { }

而clone()方法是Object类里面的方法,实现Cloneable接口只是告诉虚拟机此类的对象支持复制,我们实现这个接口之后输出的内容如下:

这就是深拷贝,上面输出true的为浅拷贝。

总结:

浅拷贝的明显特征为:多个引用指向了同一块堆内存空间,任意改变一个引用都会导致其他引用的值发生变化。

深拷贝的明显特征为:在内存中又开辟了新的一块空间,指向了不同的内存块,改变一个引用是不会影响另外一个引用的。

你可能感兴趣的:(Java基础)