การเรียก clone () บนอาร์เรย์จะโคลนเนื้อหาด้วยหรือไม่


92

ถ้าฉันเรียกใช้clone()เมธอดบนอาร์เรย์ของ Objects ประเภท A มันจะโคลนองค์ประกอบของมันได้อย่างไร? สำเนาจะอ้างอิงถึงวัตถุเดียวกันหรือไม่ หรือจะเรียกร้อง(element of type A).clone()ให้แต่ละคน?


3
คุณต้องเรียกโคลนในแต่ละองค์ประกอบ
Peter Lawrey

คำตอบ:


77

clone()สร้างสำเนาตื้น ๆ ซึ่งหมายความว่าองค์ประกอบจะไม่ถูกโคลน (จะเกิดอะไรขึ้นถ้าพวกเขาไม่ได้ใช้Cloneable?)

คุณอาจต้องการใช้Arrays.copyOf(..)สำหรับคัดลอกอาร์เรย์แทนclone()(แม้ว่าการโคลนจะใช้ได้ดีสำหรับอาร์เรย์ซึ่งแตกต่างจากสิ่งอื่นใด)

หากคุณต้องการโคลนลึกตรวจสอบคำตอบนี้


ตัวอย่างเล็ก ๆ น้อย ๆ เพื่อแสดงให้เห็นถึงความตื้นของclone()แม้ว่าองค์ประกอบต่างๆจะเป็นCloneableดังนี้:

ArrayList[] array = new ArrayList[] {new ArrayList(), new ArrayList()};
ArrayList[] clone = array.clone();
for (int i = 0; i < clone.length; i ++) {
    System.out.println(System.identityHashCode(array[i]));
    System.out.println(System.identityHashCode(clone[i]));
    System.out.println(System.identityHashCode(array[i].clone()));
    System.out.println("-----");
}

พิมพ์:

4384790  
4384790
9634993  
-----  
1641745  
1641745  
11077203  
-----  

2
และถ้าคุณจะทำเช่นนั้นโดยส่วนตัวฉันจะใช้System.arrayCopy
corsiKa

1
clone()เป็นตัวเลือกที่ดีสำหรับใช้กับอาร์เรย์.. โดยเฉพาะ Bloch กล่าวว่าเขาจะใช้มันสำหรับอาร์เรย์เท่านั้นและไม่มีอะไรอื่น System.arrayCopyสบายดี. Arrays.copyOf(..)เป็นอีกทางเลือกหนึ่งที่ใช้งานง่ายกว่า
Bozho

ฉันเอามันกลับมา - ฉันจะใช้Arrays.copyOf:-) มันมีลายเซ็นวิธีที่ทำให้ตัวแปรง่ายขึ้น (ใช่มัน จำกัด คุณ แต่มันเหมาะสำหรับกรณีส่วนใหญ่) และใน JDK ของฉันอย่างน้อยมันก็ใช้งานได้System.arrayCopyอยู่ดี ขอบคุณสำหรับเคล็ดลับ!
corsiKa

@Bozho จากเช่นของคุณ array [i] และ clone [i] จะอ้างถึงอ็อบเจ็กต์เดียวกันดังนั้นสอง sysouts แรกจึงเหมือนกัน แต่อาร์เรย์ [i] .clone จะอ้างถึงอาร์เรย์ [i] ด้วยเหตุใดอาร์เรย์ [i] .clone () จึงส่งคืนค่าแฮชโค้ดที่แตกต่างกัน
abhihello123

@weakstudent, ไม่ได้หมายถึงarray[i].clone() array[i]นั่นคือส่วนหนึ่งของตัวอย่างที่แสดงให้เห็น
Dathan

19

ถ้าฉันเรียกใช้เมธอด clone () บนอาร์เรย์ของ Objects ประเภท A มันจะโคลนองค์ประกอบของมันได้อย่างไร?

องค์ประกอบของอาร์เรย์จะไม่ถูกโคลน

สำเนาจะอ้างอิงถึงวัตถุเดียวกันหรือไม่

ใช่.

หรือจะเรียก (องค์ประกอบประเภท A) .clone () สำหรับแต่ละคน?

ไม่มันจะไม่เรียกclone()ใช้องค์ประกอบใด ๆ


6

อาร์เรย์ 1D ดั้งเดิมจะคัดลอกองค์ประกอบเมื่อถูกโคลน สิ่งนี้ล่อลวงให้เราโคลนอาร์เรย์ 2 มิติ (Array of Arrays)

โปรดจำไว้ว่า 2D clone()โคลนอาร์เรย์ไม่ทำงานเนื่องจากตื้นดำเนินงานสำเนาของ

public static void main(String[] args) {
    int row1[] = {0,1,2,3};
    int row2[] =  row1.clone();
    row2[0] = 10;
    System.out.println(row1[0] == row2[0]); // prints false

    int table1[][]={{0,1,2,3},{11,12,13,14}};
    int table2[][] = table1.clone();
    table2[0][0] = 100;
    System.out.println(table1[0][0] == table2[0][0]); //prints true
}

1
คุณกำลังบอกฉันว่าฉันสามารถcloneอาร์เรย์ 1D ของดั้งเดิมและรับสำเนาลึกได้หรือไม่? สุดยอดมาก! ค่าโดยสารได้ดีArrays.copyOfRange(), System.arraycopy()!
Janez Kuhar

1
เยสสสสสส! อาร์เรย์แบบดั้งเดิม 1D จะถูกคัดลอกเมื่ออาร์เรย์ถูกโคลน
ธัมมี่โกวด้า

1
โปรดทราบว่า Thame Gowda N พูดว่า "ดึกดำบรรพ์" การโคลนอาร์เรย์ของออบเจ็กต์จะเป็นเพียงการโคลนการอ้างอิง
Kristiaan

เนื่องจากดึกดำบรรพ์ไม่มีสถานะจึงไม่เปลี่ยนรูปโดยเนื้อแท้ คุณไม่สามารถทำสำเนาดั้งเดิมแบบตื้น ๆ ได้เนื่องจากไม่มีข้อมูลอ้างอิง
Xerus

5

โคลนคือสำเนาตื้นของอาร์เรย์

รหัสทดสอบนี้พิมพ์:

[1, 2] / [1, 2]
[100, 200] / [100, 2]

เนื่องจากMutableIntegerมีการแชร์ในอาร์เรย์ทั้งสองเป็นobjects[0]และobjects2[0]แต่คุณสามารถเปลี่ยนการอ้างอิงได้objects[1]โดยobjects2[1]ไม่ขึ้นกับ.

import java.util.Arrays;                                                                                                                                 

public class CloneTest {                                                                                                                                 
    static class MutableInteger {                                                                                                                        
        int value;                                                                                                                                       
        MutableInteger(int value) {                                                                                                                      
            this.value = value;                                                                                                                          
        }                                                                                                                                                
        @Override                                                                                                                                        
        public String toString() {                                                                                                                       
            return Integer.toString(value);                                                                                                              
        }                                                                                                                                                
    }                                                                                                                                                    
    public static void main(String[] args) {                                                                                                             
        MutableInteger[] objects = new MutableInteger[] {
                new MutableInteger(1), new MutableInteger(2) };                                                
        MutableInteger[] objects2 = objects.clone();                                                                                                     
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                                
        objects[0].value = 100;                                                                                                                          
        objects[1] = new MutableInteger(200);                                                                                                            
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.