Чи клонує клонування () масиву також клонування його вмісту?


92

Якщо я викликаю clone()метод на масиві Об'єктів типу A, як він клонуватиме свої елементи? Чи буде копія посилатися на ті самі об'єкти? Або це покличе (element of type A).clone()кожного з них?


3
Вам потрібно викликати клон на кожному елементі.
Пітер Лорі

Відповіді:


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()це хороший варіант для використання з масивами .. майже виключно. Блок згадує, що використовував би його лише для масивів і нічого іншого. System.arrayCopyдобре. Arrays.copyOf(..)є ще однією альтернативою, яку простіше використовувати.
Божо

Я беру його назад - я б використав 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 () для масиву Об’єктів типу A, як він клонуватиме свої елементи?

Елементи масиву не будуть клоновані.

Чи буде копія посилатися на ті самі об'єкти?

Так.

Або він буде викликати (елемент типу A) .clone () для кожного з них?

Ні, це не буде clone()використовувати будь-який з елементів.


6

1D масив примітивів копіює елементи при клонуванні. Це спокушає нас клонувати 2D-масив (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
Ви кажете мені, що я можу clone1D масив примітивів і отримати глибоку копію? Це так чудово! Вартість проїзду добре Arrays.copyOfRange(), System.arraycopy()!
Janez Kuhar

1
Такссссс! 1D масив примітивів копіюється при клонуванні масиву
Thamme Gowda

1
Зверніть увагу, що Тхамме Гоуда Н каже "примітиви". Клони масивів об'єктів будуть просто клоном посилань.
Крістіан

оскільки примітиви не мають стану, вони за своєю суттю незмінні. Ви не можете зробити дрібну копію примітивів, оскільки посилання на це немає
Ксер

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));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.