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.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 i System.arrayCopy
tak. 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
}
clone
tablicę 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ż MutableInteger
jest 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));
}
}