📜  Java示例的深、浅和惰性复制

📅  最后修改于: 2022-05-13 01:55:49.943000             🧑  作者: Mango

Java示例的深、浅和惰性复制

在面向对象编程中,对象复制是创建现有对象的副本,生成的对象称为对象副本或简称为原始对象的副本。复制对象有多种方法,最常见的是通过复制构造函数或克隆.
我们可以将克隆定义为“创建对象的副本”。浅拷贝、深拷贝和惰性拷贝与克隆过程有关。
这实际上是创建复制对象的三种方式。
浅拷贝

  • 每当我们使用克隆方法的默认实现时,我们都会得到对象的浅拷贝,这意味着它会创建新实例并将对象的所有字段复制到该新实例并将其作为对象类型返回,我们需要将其显式转换回原始对象。这是对象的浅拷贝。
  • 对象类的 clone() 方法支持对象的浅拷贝。如果对象在浅拷贝中包含原始以及非原始或引用类型变量,则克隆对象还引用原始对象所引用的同一对象,因为仅复制对象引用而不是引用对象本身。
  • 这就是为什么在Java中称为浅拷贝或浅克隆的原因。如果只有原始类型字段或不可变对象,那么Java中的浅拷贝和深拷贝没有区别。

Java
//code illustrating shallow copy
public class Ex {
 
    private int[] data;
 
    // makes a shallow copy of values
    public Ex(int[] values) {
        data = values;
    }
 
    public void showData() {
        System.out.println( Arrays.toString(data) );
    }
}


Java
public class UsesEx{
 
    public static void main(String[] args) {
        int[] vals = {3, 7, 9};
        Ex e = new Ex(vals);
        e.showData(); // prints out [3, 7, 9]
        vals[0] = 13;
        e.showData(); // prints out [13, 7, 9]
 
        // Very confusing, because we didn't
        // intentionally change anything about
        // the object e refers to.
    }
}


Java
// Code explaining deep copy
public class Ex {
     
    private int[] data;
 
    // altered to make a deep copy of values
    public Ex(int[] values) {
        data = new int[values.length];
        for (int i = 0; i < data.length; i++) {
            data[i] = values[i];
        }
    }
 
    public void showData() {
        System.out.println(Arrays.toString(data));
    }
}


Java
public class UsesEx{
 
    public static void main(String[] args) {
        int[] vals = {3, 7, 9};
        Ex e = new Ex(vals);
        e.showData(); // prints out [3, 7, 9]
        vals[0] = 13;
        e.showData(); // prints out [3, 7, 9]
 
       // changes in array values will not be
       // shown in data values.
    }
}


上面的代码显示了浅拷贝。 data 只是指与 vals 相同的数组。

如果通过其他引用更改值的元素,这可能会导致令人不快的副作用。

Java

public class UsesEx{
 
    public static void main(String[] args) {
        int[] vals = {3, 7, 9};
        Ex e = new Ex(vals);
        e.showData(); // prints out [3, 7, 9]
        vals[0] = 13;
        e.showData(); // prints out [13, 7, 9]
 
        // Very confusing, because we didn't
        // intentionally change anything about
        // the object e refers to.
    }
}
Output 1 : [3, 7, 9]
Output 2 : [13, 7, 9]

深拷贝

  • 每当我们需要自己的副本而不使用默认实现时,我们将其称为深副本,每当我们需要对象的深副本时,我们需要根据需要实现。
  • 所以对于深拷贝,我们需要确保所有的成员类也实现了 Cloneable 接口并覆盖了对象类的 clone() 方法。

深拷贝意味着实际上创建一个新数组并复制这些值。

Java

// Code explaining deep copy
public class Ex {
     
    private int[] data;
 
    // altered to make a deep copy of values
    public Ex(int[] values) {
        data = new int[values.length];
        for (int i = 0; i < data.length; i++) {
            data[i] = values[i];
        }
    }
 
    public void showData() {
        System.out.println(Arrays.toString(data));
    }
}



Java

public class UsesEx{
 
    public static void main(String[] args) {
        int[] vals = {3, 7, 9};
        Ex e = new Ex(vals);
        e.showData(); // prints out [3, 7, 9]
        vals[0] = 13;
        e.showData(); // prints out [3, 7, 9]
 
       // changes in array values will not be
       // shown in data values.
    }
}
Output 1 : [3, 7, 9]
Output 2 : [3, 7, 9]