Czy wywołanie clone () w tablicy również klonuje jej zawartość?
92
Jeśli wywołam clone()metodę na tablicy obiektów typu A, w jaki sposób sklonuje jej elementy? Czy kopia będzie odnosić się do tych samych obiektów? A może wezwie (element of type A).clone()każdego z nich?
Mały przykład ilustrujący płytkość, clone()nawet jeśli elementy są 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("-----");
}
A jeśli miałbyś to zrobić, osobiście System.arrayCopy
użyłbym
1
clone()jest dobrą opcją do stosowania z tablicami… prawie wyłącznie. Bloch wspomina, że używałby go tylko do tablic i nic więcej. System.arrayCopyjest w porządku. Arrays.copyOf(..)to kolejna alternatywa, która jest łatwiejsza w użyciu.
Bozho
Cofam to - Arrays.copyOfużyłbym :-) Ma sygnaturę metody, która upraszcza zmienne (tak, ogranicza cię, ale jest idealna w większości przypadków) iw moim JDK przynajmniej jest zaimplementowana przy użyciu i System.arrayCopytak. Dzięki za tę wskazówkę!
corsiKa
@Bozho, z Twojego np. array [i] i clone [i] będą odnosić się do tego samego obiektu, więc pierwsze dwa sysouty są takie same. Ale tablica [i] .clone odnosiłaby się również do samej tablicy [i], więc dlaczego tablica [i] .clone () zwraca inną wartość kodu skrótu?
abhihello123
@weakstudent, array[i].clone()NIE odnosi się do array[i]. To właśnie pokazuje ta część przykładu.
Dathan
19
Jeśli wywołam metodę clone () na tablicy obiektów typu A, w jaki sposób sklonuje ona swoje elementy?
Elementy tablicy nie zostaną sklonowane.
Czy kopia będzie odnosić się do tych samych obiektów?
Tak.
A może wywoła (element typu A) .clone () dla każdego z nich?
Nie, nie będzie odwoływać clone()się do żadnego z elementów.
Mówisz mi, że mogę clonetablicę prymitywów 1D i uzyskać głęboką kopię? To jest tak niesamowite! Radzą sobie dobrze Arrays.copyOfRange(), System.arraycopy()!
Janez Kuhar
1
Yessssss! Tablica 1D prymitywów jest kopiowana po sklonowaniu tablicy
Thamme Gowda
1
Zwróć uwagę, że Thamme Gowda N mówi „prymitywy”. Klony tablic obiektów będą po prostu klonem odniesień.
Kristiaan
ponieważ prymitywy nie mają stanu, są z natury niezmienne. Nie możesz zrobić płytkiej kopii prymitywów, ponieważ nie ma odniesienia
Xerus
5
Klon jest płytką kopią tablicy.
Ten kod testowy drukuje:
[1, 2] / [1, 2]
[100, 200] / [100, 2]
ponieważ MutableIntegerjest on współdzielony w obu tablicach jako objects[0]i objects2[0], ale możesz zmienić odwołanie objects[1]niezależnie od objects2[1].
Odpowiedzi:
clone()
tworzy płytką kopię. Co oznacza, że elementy nie zostaną sklonowane. (A co, jeśli nie wdrożyliCloneable
?)Możesz użyć
Arrays.copyOf(..)
do kopiowania tablic zamiastclone()
(chociaż klonowanie jest dobre dla tablic, w przeciwieństwie do czegokolwiek innego)Jeśli chcesz głębokiego klonowania, sprawdź tę odpowiedź
Mały przykład ilustrujący płytkość,
clone()
nawet jeśli elementy są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("-----"); }
Wydruki:
4384790 4384790 9634993 ----- 1641745 1641745 11077203 -----
źródło
System.arrayCopy
clone()
jest dobrą opcją do stosowania z tablicami… prawie wyłącznie. Bloch wspomina, że używałby go tylko do tablic i nic więcej.System.arrayCopy
jest w porządku.Arrays.copyOf(..)
to kolejna alternatywa, która jest łatwiejsza w użyciu.Arrays.copyOf
użyłbym :-) Ma sygnaturę metody, która upraszcza zmienne (tak, ogranicza cię, ale jest idealna w większości przypadków) iw moim JDK przynajmniej jest zaimplementowana przy użyciu iSystem.arrayCopy
tak. Dzięki za tę wskazówkę!array[i].clone()
NIE odnosi się doarray[i]
. To właśnie pokazuje ta część przykładu.Elementy tablicy nie zostaną sklonowane.
Tak.
Nie, nie będzie odwoływać
clone()
się do żadnego z elementów.źródło
Tablica 1D prymitywów kopiuje elementy podczas klonowania. Kusi nas to do sklonowania tablicy 2D (Array of Arrays).
Pamiętaj, że klon tablicy 2D nie działa z powodu płytkiej implementacji kopii
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 }
źródło
clone
tablicę prymitywów 1D i uzyskać głęboką kopię? To jest tak niesamowite! Radzą sobie dobrzeArrays.copyOfRange()
,System.arraycopy()
!Klon jest płytką kopią tablicy.
Ten kod testowy drukuje:
ponieważ
MutableInteger
jest on współdzielony w obu tablicach jakoobjects[0]
iobjects2[0]
, ale możesz zmienić odwołanieobjects[1]
niezależnie odobjects2[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)); } }
źródło