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?
Odpowiedzi:
clone()tworzy płytką kopię. Co oznacza, że elementy nie zostaną sklonowane. (A co, jeśli nie wdrożyli Cloneable?)
Możesz użyć Arrays.copyOf(..)do kopiowania tablic zamiast clone()(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
-----
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.arrayCopyjest w porządku. Arrays.copyOf(..)to kolejna alternatywa, która jest łatwiejsza w użyciu.
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ę!
array[i].clone()NIE odnosi się do array[i]. To właśnie pokazuje ta część przykładu.
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.
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
}
clonetablicę prymitywów 1D i uzyskać głęboką kopię? To jest tak niesamowite! Radzą sobie dobrze Arrays.copyOfRange(), System.arraycopy()!
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].
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));
}
}