簡體   English   中英

Java - 實現數組的深層和淺層副本

[英]Java - Implement deep and shallow copy of an array

我試圖理解Java中淺層和深層復制的概念。 關於這個主題有很多文章和問答,但每當我嘗試在真正的Java代碼中實現這些概念時,我都不清楚一切。

我基於理解的答案之一就是在這個鏈接中 ,通過模式解釋深度和淺層復制。

我會在每個案例的實施情況下向您展示:

  • 淺拷貝:

我在我的示例中使用了System.arraycopy()方法,因為我在許多文章中讀到它執行淺拷貝(以及克隆方法)

public class Test {

    public static void main(String[] args) {
        NameValue[] instance1 = {
                new NameValue("name1", 1),
                new NameValue("name2", 2),
                new NameValue("name3", 3),
        };
        NameValue[] instance2 = new NameValue[instance1.length];

        // Print initial state
        System.out.println("Arrays before shallow copy:");
        System.out.println("Instance 1: " + Arrays.toString(instance1));
        System.out.println("Instance 2: " + Arrays.toString(instance2));

        // Perform shallow copy
        System.arraycopy(instance1, 0, instance2, 0, 3);

        // Change instance 1
        for (int i = 0; i < 3; i++) {
            instance1[i].change();
        }

        // Print final state
        System.out.println("Arrays after shallow copy:");
        System.out.println("Instance 1: " + Arrays.toString(instance1));
        System.out.println("Instance 2: " + Arrays.toString(instance2));
    }

    private static class NameValue {
        private String name;
        private int value;

        public NameValue(String name, int value) {
            super();
            this.name = name;
            this.value = value;
        }

        public void change() {
            this.name = this.name + "-bis";
            this.value = this.value + 1;
        }

        @Override
        public String toString() {
            return this.name + ": " + this.value;
        }
    }
}

執行主要方法的結果如下:

Arrays before shallow copy:
Instance 1: [name1: 1, name2: 2, name3: 3]
Instance 2: [null, null, null]
Arrays after shallow copy:
Instance 1: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
Instance 2: [name1-bis: 2, name2-bis: 3, name3-bis: 4]

此結果符合上一個鏈接的架構: 淺拷貝

  • 深拷貝:

我在這個例子中使用了Arrays.copyOf()方法,因為我在許多文章中讀到它執行深層復制(以及Arrays.copyOfRange方法)

public static void main(String[] args) {
    NameValue[] instance1 = {
            new NameValue("name1", 1),
            new NameValue("name2", 2),
            new NameValue("name3", 3),
    };
    NameValue[] instance2 = new NameValue[instance1.length];

    // Print initial state
    System.out.println("Arrays before deep copy:");
    System.out.println("Instance 1: " + Arrays.toString(instance1));
    System.out.println("Instance 2: " + Arrays.toString(instance2));

    // Perform deep copy
    instance2 = Arrays.copyOf(instance1, 3);

    // Change instance 1
    for (int i = 0; i < 3; i++) {
        instance2[i].change();
    }

    // Print final state
    System.out.println("Arrays after deep copy:");
    System.out.println("Instance 1: " + Arrays.toString(instance1));
    System.out.println("Instance 2: " + Arrays.toString(instance2));
}

顯示:

Arrays before deep copy:
Instance 1: [name1: 1, name2: 2, name3: 3]
Instance 2: [null, null, null]
Arrays after deep copy:
Instance 1: [name1-bis: 2, name2-bis: 3, name3-bis: 4]
Instance 2: [name1-bis: 2, name2-bis: 3, name3-bis: 4]

如果我們將深層復制邏輯基於先前的模式,那么結果應該是: 深拷貝

您可能會注意到,main方法的執行結果與上面的模式邏輯不同。

任何解釋都將受到歡迎。

我不知道你在哪里讀到copyOf()執行深層復制,因為這是完全錯誤的。

引用Arrays.copyOf(T[] original, int newLength) javadoc:

對於在原始數組和副本中都有效的所有索引, 這兩個數組將包含相同的值

這意味着它是一個淺薄的副本。 要成為深層副本,值必須指向不同的對象,因為引用的對象也必須是副本。

要執行深層復制, 必須迭代數組並復制值。 Java無法為您做到這一點,因為它不知道如何復制對象。

例如,Java如何知道如何復制NameValue對象? clone() 復制構造函數? 序列化+反序列化? 工廠方法? 其他方法?

我試圖理解Java中淺層和深層復制的概念。

在Java中,您傳遞並存儲對象的引用而不是對象本身。
因此,當您擁有NameValue[] array該數組不包含對象NameValue而是對對象的引用。
因此,當您對NameValue[] array2執行淺復制時,這意味着您只是將引用從一個數組復制到另一個數組。 這實際上意味着現在arrayarray2指向完全相同的對象,並且從array2[2] (同一個對象)可以看到從array[2]進行的任何更改。

深度復制時,將每個對象完全復制到另一個內存區域,並在新陣列中保留對該新對象的引用。
這樣,2個數組現在引用不同的對象,並且從array2[2]看不到對array[2]任何更改

更新:
這不適用於存儲實際值而不是引用的基元。
所以當你復制時你得到一個int[] a得到一個值的副本(即某種意義上的深拷貝),因為a[2]包含值本身而不是對值的引用。

我認為有一點誤解, Arrays.copyOf()會生成一個深層副本。

Arrays.copyOf()創建一個新數組,其中包含對未被復制的對象的舊Arrays.copyOf() ,並且我添加的鏈接在嵌套數組的情況下解釋它們不會被復制,因此它不能被視為拷貝,但淺拷貝。

有關更多信息,請參閱

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM