zoukankan      html  css  js  c++  java
  • Java 浅拷贝和深拷贝

    1.前言

    之前的博文 Java 返回可变引用对象的相关问题中,对于可变变量,有使用 clone()方法,防止破坏封装,还没有较深入的介绍克隆方法,这篇博文将进一步介绍。

    2.clone()方法

    protected Object clone() throws CloneNotSupportedException

    创建并返回此对象的副本。 “复制”的确切含义可能取决于对象的类别。 一般意图是,对于任何对象x ,表达式为: x.clone() != x

    按照惯例,返回的对象应该通过调用super.clone获得。 如果一个类及其所有超类(除了Object )遵守这个约定,那将是x.clone().getClass() == x.getClass()的情况。

    通常,这意味着复制包含被克隆对象的内部“深层结构”的任何可变对象,并使用对副本的引用替换对这些对象的引用。 如果一个类只包含原始字段或对不可变对象的引用,那么通常情况下不需要修改super.clone返回的对象中的任何字段。

    Object的方法clone执行特定的克隆操作。 首先,如果此对象的类未实现接口Cloneable ,则抛出CloneNotSupportedException 。 请注意,所有数组都被视为实现接口Cloneable并且数组类型T[]clone方法的返回类型是T[] ,其中T是任何引用或基本类型。 否则,此方法创建此对象的类的新实例,并使用该对象的相应字段的内容初始化其所有字段,就像通过赋值一样; 这些字段的内容本身不会被克隆。 因此,该方法执行该对象的“浅拷贝”,而不是“深拷贝”操作。

    Object本身不实现接口Cloneable ,因此在类为Object的对象上调用clone方法将导致在运行时抛出异常。

    提到一个类中如果包含任何可变对象,并使用对副本的引用替换对这些对象的引用,即引入浅拷贝深拷贝概念

    3.浅拷贝

    默认的克隆操作是“ 浅拷贝”,并没有克隆对象中引用的其他对象。

    public class Employee implements Cloneable{
        private String name;
        private double salary;
        private Date hireDay;
    
        public Employee clone() throws CloneNotSupportedException {
            return (Employee) super.clone();
        }
        ...
    }
    

    下图显示了使用Object 类的 clone 方法克隆这样一个 Employee 对象会发生什么。可以看到, 默认的克隆操作是“ 浅拷贝”,并没有克隆对象中引用的其他对象。

    如果原对象和浅克隆对象共享的子对象是不可变的, 那么这种共享就是安全的。

    在这个例子中,hireDay 域是一个 Date , 这是可变的, 所以它也需要克隆。(出如果 hireDay是不可变的 LocalDate 类的一个实例,就无需我们做任何处理了。)

    ​ 对于每一个类,需要确定:

    1 ) 默认的 clone 方法是否满足要求;

    2 ) 是否可以在可变的子对象上调用 clone 来修补默认的 clone 方法;

    3 ) 是否不该使用 clone

    ​ 实际上第 3 个选项是默认选项。如果选择第 1 项或第 2 项,类必须:

    1 ) 实现 Cloneable 接口;

    2 ) 重新定义 clone 方法,并指定 public 访问修饰符

    4.深拷贝

    public class Employee implements Cloneable{
        private String name;
        private double salary;
        private Date hireDay;
    
        public Employee clone() throws CloneNotSupportedException {
            // call Object.clone()
            Employee cloned = (Employee) super.clone();
            //clone mutable fields
            cloned.hireDay = (Date) hireDay.clone();
            return cloned;
        }
        ...
    }
    

    所有的数组类型都有一个 publicclone 方法, 而不是 protected

    5.另一种克隆对象的机制

    待补充

  • 相关阅读:
    POJ 2029 (二维树状数组)题解
    HDU 4819 Mosaic (二维线段树&区间最值)题解
    HDU 1823 Luck and Love (二维线段树&区间最值)题解
    POJ1061 青蛙的约会(扩展欧几里得)题解
    POJ 2155 Matrix (二维树状数组)题解
    POJ 1751 Highways(最小生成树&Prim)题解
    HDU 6148 Valley Numer (数位DP)题解
    HDU3652 B-number(数位DP)题解
    HDU 4734 (数位DP)题解
    HDU 2089 不要62 (数位DP)题解
  • 原文地址:https://www.cnblogs.com/huaranmeng/p/12796918.html
Copyright © 2011-2022 走看看