Другой перечисленный Стандартом C++:
#include <stdio.h>
int x[1];
int main(void) {
struct x { int a[2]; };
/* size of the array in C */
/* size of the struct in C++ */
printf("%d\n", (int)sizeof(x));
}
Да, это правильно - вам необходимо реализовать clone ()
(или другой подходящий механизм для копирования вашего объекта, поскольку считается clone ()
» сломан "многими программистами). Ваш метод clone ()
должен выполнять глубокую копию всех изменяемых полей в вашем объекте. Таким образом, изменения клонированного объекта не повлияют на оригинал.
В вашем примере кода вы создаете второй ArrayList
и заполняете его ссылками на те же объекты , поэтому изменения в объекте видны из обоих List
s. При использовании подхода клонирования ваш код будет выглядеть так:
List<Foo> originalList = ...;
// Create new List with same capacity as original (for efficiency).
List<Foo> copy = new ArrayList<Foo>(originalList.size());
for (Foo foo: originalList) {
copy.add((Foo)foo.clone());
}
РЕДАКТИРОВАТЬ : Чтобы уточнить, приведенный выше код выполняет глубокую копию исходного Списка
, при этом новый Список
содержит ссылки на копии исходных объектов. Это контрастирует с вызовом ArrayList.clone ()
, который выполняет мелкую копию
списка List
. В этом контексте неглубокая копия создает новый экземпляр List
, но содержащий ссылки на исходные объекты.
Я подумал, что могу изменить элементы внутри copiedInvoice, и это не повлияет на эти элементы внутри originalInoice.
Это происходит потому, что копируется ссылочная переменная, а не сам объект.
Таким образом, вы получаете две «ссылки», указывающие на один и тот же объект.
Если вам нужно скопировать весь объект, вам может потребоваться его клонирование.
Но у вас могут возникнуть проблемы, если вы не клонируете внутренние атрибуты объекта, если они являются другими объектами.
Например, следующее определение класса не вызовет у вас никаких проблем.
public class Something {
private int x;
private int y;
private String stringObject;
}
Если вы создадите копию этого класса, вы скопируете текущие значения его атрибутов и все.
Но если у вашего класса есть другой объект внутри, вы можете подумать о его клонировании.
class OtherSomething {
Something something;
private int x;
}
Если вы сделаете следующее:
Something shared = new Something();
OtherSomething one = new OtherSomething();
OtherSomething two = new OtherSomething();
one.something = shared;
two.something = shared;
В этом случае и один, и два имеют одну и ту же ссылочную переменную на одно и то же совместно используемое «что-то», и изменение значения в одном из них повлияет на другое.
Вот почему гораздо проще / лучше / проще использовать неизменяемые объекты.
Если вам нужно изменить значение неизменяемого объекта, вы просто создаете новый с правильным значением.
Если вы сохраняете изменяемые объекты в ArrayList, вам нужно будет скопировать каждый объект при копировании ArrayList. В противном случае новый список ArrayList по-прежнему будет содержать исходные ссылки.
Однако, если вы храните неизменяемые объекты, можно использовать:
ArrayList copiedInvoice = new ArrayList (originalInvoice);
Взгляните на ByteArrayOutputStream и ByteArrayInputStream. Если все ваши классы реализуют Serializable, вы можете сделать копию, используя вышеупомянутые классы.