Как сделать копию объекта java

Как сделать глубокую копию объекта в Java?

в java немного сложно реализовать функцию глубокой копии объекта. Какие шаги вы предпринимаете, чтобы гарантировать, что исходный объект и клонированный один не имеют ссылки?

17 ответов:

безопасный способ-сериализовать объект, а затем десериализовать. Это гарантирует, что все является совершенно новой ссылкой.

вот статья о том, как сделать это эффективно.

предостережения: классы могут переопределять сериализацию таким образом, что новые экземпляры не создано, например, для синглетов. Также это, конечно, не работает, если ваши классы не Сериализуемы.

схемы, которые полагаются на сериализацию (XML или иначе) являются несколько аляповата.

здесь нет простого ответа. Если вы хотите глубоко скопировать объект, вам придется пересечь граф объектов и скопировать каждый дочерний объект явно с помощью конструктора копирования объекта или статического метода фабрики, который в свою очередь глубоко копирует дочерний объект. Неизменяемые (например String s) не нужно копировать. В стороне, вы должны поддерживать неизменность по этой причине.

вы можете сделать глубокую копию с сериализацией без создания файлов.

преобразовать свой класс в поток байтов:

восстановить класс из потока байтов:

вы можете сделать глубокий клон на основе сериализации с помощью org.apache.commons.lang3.SerializationUtils.clone(T) в Apache Commons Lang, но будьте осторожны-производительность ужасна.

В общем случае рекомендуется писать собственные методы клонирования для каждого класса объекта в графе объектов, нуждающихся в клонировании.

одним из способов реализации глубокого копирования является добавление конструкторов копирования в каждый связанный класс. Конструктор копирования принимает экземпляр ‘this’ в качестве единственного аргумента и копирует из него все значения. Довольно небольшая работа, но довольно простая и безопасная.

EDIT: обратите внимание, что вам не нужно использовать методы доступа для чтения полей. Вы можете получить доступ ко всем полям напрямую, потому что исходный экземпляр всегда имеет тот же тип, что и экземпляр с конструктором копирования. Очевидно, но может быть упущенный.

Edit: обратите внимание, что при использовании конструкторов копирования необходимо знать тип среды выполнения копируемого объекта. При вышеуказанном подходе вы не можете легко скопировать смешанный список (вы можете сделать это с помощью некоторого кода отражения).

Apache commons предлагает быстрый способ глубокого клонирования объекта.

Источник

Копирование объектов в Java

я узнал, что при изменении переменной в Java она не изменяет переменную, на которой она была основана

я предположил аналогичную вещь для объектов. Рассмотрим этот класс.

после того как я попробовал этот код, я запутался.

пожалуйста, объясните мне, почему изменение любого из объектов влияет на другой. Я понимаю, что значение переменной text хранится в одном и том же месте в памяти для обоих объектов.

почему значения переменных независимы, но коррелированы для объектов?

кроме того, как дублировать SomeObject, если простое назначение не выполняет эту работу?

16 ответов:

каждая переменная в Java-это ссылка. Так что, когда вы делаете

в конце концов, все присваивается по значению, это просто значение ссылки, а не значение объекта (за исключением примитивных типов, как упомянутый выше.)

С помощью этого вы можете скопировать объект довольно легко:

ответ @ brimborium очень хорош (+1 для него), но я просто хочу подробнее рассказать об этом, используя некоторые цифры. Давайте сначала примитивное задание:

после создания целочисленного объекта и до задание:

Как сделать копию объекта java

Как сделать копию объекта java

(целочисленный объект теперь имеет право на сбор мусора, но не обязательно сбор мусора еще на этом этапе)

Как сделать копию объекта java

Как сделать копию объекта java

Как сделать копию объекта java

Как сделать копию объекта java

3-Когда вы используете сеттеры на ссылке, он будет изменять объект на что указывает ссылка.

Как сделать копию объекта java

у вас есть 2 ссылки на один и тот же объект. Это означает, что какой бы ссылочный объект вы ни использовали, внесенные изменения будут видны при использовании второй ссылки.

подумайте об этом так: у вас есть один телевизор в комнате, но два пульта дистанционного управления: неважно, какой пульт вы используете, вы все равно будете вносить изменения в один и тот же базовый объект (телевизор).

6-путаница при передаче по значению и передаче по ссылке

это может быть проблемой для диагностики, потому что, когда вы смотрите в коде, вы можете быть уверены, что пройдя по ссылке, но найти что его на самом деле передается по значению. Java использует оба, поэтому вам нужно чтобы понять, когда вы проходите мимо значения, и когда вы проходите мимо ссылка.

при передаче примитивного типа данных, например char, int, float или дважды, к функции, то вы передаете по значению. Это означает, что копия типа данных дублируется и передается в функцию. Если функция выбирает, чтобы изменить это значение, оно будет изменять только копирование. Как только функция завершится, и управление будет возвращено возвращаемая функция,» реальная » переменная будет нетронутой, и нет изменения будут сохранены. Если вам нужно чтобы изменить примитивные данные введите, сделайте его возвращаемым значением для функции или оберните его внутри объект.

SomeObject s2 = s1; сделать s1 и s2 две ссылки на один и тот же объект, так что если вы измените один, другой будет изменен тоже.

хорошим решением является реализация другого конструктор вроде этого:

тогда используйте его так:

The + оператор на целых числах создает новая объект, он не изменяет существующий объект (поэтому добавление 5+5 не дает 5 новое значение 10. ).

The = оператор присваивает значение указателя. Он не копирует объект.

клонирование объектов является сложным делом само по себе. Каждый объект имеет метод clone (), который вы может возникнуть соблазн использовать, но он делает мелкую копию (что в основном означает, что он делает копию объекта верхнего уровня, но любой объект, который содержится в нем, не клонируется). Если вы хотите поиграть с копиями объектов, обязательно прочитайте Joshua Bloch’s Эффективная Java.

давайте начнем со второго примера:

это первый оператор присваивает новый объект s1

при выполнении задания во втором операторе ( SomeObject s2 = s1 ), ты говоришь s2 указывать на один и тот же объект s1 в настоящее время указывает на, так что у вас есть две ссылки на один и тот же объект.

в вашем первом примере, a и b являются примитивными значениями, поэтому изменение одного не влияет на другие.

ответы выше объясняют поведение, которое вы видите.

в ответ на «Кроме того, как дублировать SomeObject, если простое назначение не выполняет эту работу?»- попробуйте найти cloneable (это интерфейс java, который обеспечивает один из способов копирования объектов) и ‘ copy constructors ‘ (альтернативный и, возможно, лучший подход)

назначение объекта ссылке не клонирует ваш объект. Ссылки как указатели. Они указывают на объект, и когда операции вызываются, это делается на объект, на который указывает указатель. В вашем примере s1 и s2 указывают на один и тот же объект, а сеттеры изменяют состояние одного и того же объекта, и изменения видны по ссылкам.

измените класс, чтобы создать новую ссылку вместо использования того же самого:

вы можете использовать что-то вроде этого (я не претендую на идеальное решение):

в приведенном выше случае создается новое целое число. Здесь целое-это не примитивный тип и значение внутри него преобразуется (в int) и присваивается int ‘a’.

в этом случае и s1 и s2 являются ссылочными типами. Они не создаются, чтобы содержать значение, подобное примитивным типам, а содержат ссылку на некоторый объект. Ради понимания мы можем думать о ссылке как о ссылке, которая указывает, где я могу найти объект, являющийся упоминаемый.

мы просто копируем значение, хранящееся в s1 в s2, и теперь мы знаем, что s1 содержит адрес строки «first». После этого назначения оба println () производит тот же вывод, потому что оба s1 и С2 refrencing один и тот же объект.

для получения дополнительной информации о clone () это полезная ссылка http://en.wikipedia.org/wiki/Clone_%28Java_method%29

потому что s1 и s2 работают только как ссылки на ваши объекты. При назначении s2 = s1 вы только назначаете ссылку, что означает, что оба будут указывать на один и тот же объект в памяти (объект, который имеет текущий текст «первый»).

когда вы делаете сеттер сейчас, либо на s1 или s2, оба будут изменять один и тот же объект.

когда вы назначаете и объект переменной, вы действительно назначаете ссылку на этот объект. Так что обе переменные s1 и s2 ссылаются на один и тот же объект.

Так как объекты были связаны ссылкой. Поэтому, если вы пишете s2=s1, будет скопирована только ссылка. Его, как и в C, вы обрабатывали только с адресами памяти. И если вы скопируете адрес памяти и измените значение за этим адресом, оба указателя (ссылки) изменят одно значение в этой точке в памяти.

вторая строка ( SomeObject s2 = s1; ) просто присваивает вторую переменную первой. Это приводит ко второй переменной, указывающей на тот же экземпляр объекта, что и первый.

Источник

Глубокое, мелкое и ленивое копирование с примерами Java

Мы можем определить клонирование как «создать копию объекта». Мелкая, глубокая и ленивая копия связана с процессом клонирования.
это на самом деле способы создания объекта копирования.

Мелкая копия

// код, иллюстрирующий мелкую копию

// делает поверхностную копию значений

public Ex( int [] values) <

public void showData() <

Приведенный выше код показывает мелкое копирование. Данные просто ссылаются на тот же массив, что и vals.

Как сделать копию объекта java

Это может привести к неприятным побочным эффектам, если элементы значений будут изменены с помощью какой-либо другой ссылки.

public class UsesEx<

public static void main(String[] args) <

e.showData(); // распечатывает [3, 7, 9]

e.showData(); // распечатывает [13, 7, 9]

// Очень запутанно, потому что мы этого не сделали

// намеренно изменить что-либо

// объект, на который ссылается e

Deep Copy

Глубокая копия означает на самом деле создание нового массива и копирование значений.

// Код, объясняющий глубокую копию

// изменено, чтобы сделать глубокую копию значений

public Ex( int [] values) <

data = new int [values.length];

public void showData() <

Как сделать копию объекта java

public class UsesEx<

public static void main(String[] args) <

e.showData(); // распечатывает [3, 7, 9]

e.showData(); // распечатывает [3, 7, 9]

// изменений в значениях массива не будет

// показано в значениях данных.

Изменения значений массива не приведут к изменениям данных массива.

когда использовать что
Не существует жесткого и быстрого правила, определенного для выбора между мелкой копией и глубокой копией, но обычно мы должны помнить, что если у объекта есть только примитивные поля, то, очевидно, мы должны пойти на мелкую копию, но если у объекта есть ссылки на другие объекты затем, в зависимости от требования, следует сделать мелкую или глубокую копию. Если ссылки не обновляются, то нет смысла инициировать глубокую копию.

Ленивый Копия
Ленивая копия может быть определена как комбинация как мелкой копии, так и глубокой копии. Механизм следует простому подходу — в начальном состоянии используется подход мелкого копирования. Счетчик также используется для отслеживания того, сколько объектов совместно используют данные. Когда программа хочет изменить исходный объект, она проверяет, является ли объект общим или нет. Если объект является общим, то запускается механизм глубокого копирования.

Резюме
При мелком копировании копируются только поля примитивного типа данных, а ссылки на объекты не копируются. Глубокая копия включает в себя копию примитивного типа данных, а также ссылки на объекты. Не существует жесткого и быстрого правила относительно того, когда делать мелкую копию, а когда делать глубокую копию. Ленивая копия — это комбинация обоих этих подходов.

Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное, или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.

Источник

Как создать клон объекта в Java?

Оно не подошло. Не знаю как и почему, но все переменные в новом объекте становятся ссылками на переменные старого. Т.е. в нужном месте я создал копию объекта:

и переменная someField у объекта newObject тоже стала равняться 2.

Пробовал написать мегакостыль: в классе, который надо будет копировать, создал функцию clone() и присвоил в ней всем переменным значения из существующего объекта:

И опять все тоже самое! someField в новом объекте стало равно двум. Что за чертовщина? 🙂 Прошу помощи.

Как сделать копию объекта java

Через него тоже пробовал. Та же самая канитель! В комменте ниже я написал почему, как мне кажется, ни один из этих методов не подошел. По факту они все рабочие, пока дело касается примитивных типов.

п.с. в моем случае создается объект, затем с ним производятся различные вычисления. После них создается клон текущего состояния и производятся дальнейшие вычисления над первым объектом. А клон нужен лишь для хранения «первоначального» состояния, чтобы производить дальнейшие вычисления относительно этого состояния.

Как сделать копию объекта java

Как сделать копию объекта java

User clone() <
User temp = (User)super.clone();
temp.setValue(value.clone());
return temp;
>

DR_Demons: эх, даже не знаю как бы так выдрать кусок кода, который не клонируется. наклепал в нетбинсе проект примерно с такой же структурой, как в рабочем проекте. В нем снова переменные переприсваиваются =) wxmaper.ru/temp/JavaApplication9.zip (pastebin.com/8bjcSdsc)

В примере создается 2 клона (сначала думал проблема в том, что я клонированный объект хранил в клонируемом объекте). Затем по таймеру в самый первый объект заносятся изменения, и они тут же оказываются в обоих клонированных объектах.

Первый метод в принципе бы устроил, т.к. автоматом мне нужно создать всего одного клона, один раз 🙂 в последующем новые клоны будут создаваться только действиями пользователя. А это даже не 2 раза в секунду.

О втором методе я тоже думал, но сразу же перекрестился и отбросил этот вариант.

Пока все-таки оставлю свой костыль, который просто создает 2 одинаковых объекта одновременно и выставляет у них одинаковые параметры до определенного момента. это, конечно, не совсем удобно, т.к. пришлось дублировать код в некоторых местах (не функции, слава богу, а только их вызовы :)) Но за то быстро и просто в реализации ^_^

Источник

Создание объекта Java

Java — это объектно-ориентированный язык. Другими словами, почти все в Java рассматривается как объект.

Использование ключевого слова «new»

При программировании вы наверняка сталкивались с ключевым словом «new», используемым для создания объекта, которому динамически выделяется память, т.е. память этим объектам выделяется во время выполнения. И это динамическое распределение требуется большую часть времени при создании объектов. Следовательно, этот метод используется чаще, чем другие.

Синтаксис

ClassName ObjectName = new classConstructor();

Пример

Выход — Hello World

Этот метод создания объектов в Java может использоваться с любым конструктором требуемого класса, если класс имеет более одного конструктора.

Использование метода clone()

Метод clone() можно использовать только после реализации интерфейса Cloneable и обработки исключения CloneNotSupportedException.

Пример

Вывод

Welcome to the world of programming

В приведенной выше программе мы создали копию нашего уже существующего объекта. Чтобы обе переменные не указывали на одну и ту же ячейку памяти, было важно изменить значение «FirstString» для второго объекта, а затем распечатать его значение для обоих объектов.

Использование метода newInstance() класса Class

Этот метод не часто используется для создания объектов, в случаях, когда мы знаем имя класса, а конструктор по умолчанию является публичным по своей природе. Чтобы использовать его, нам нужно обработать 3 исключения

Пример

Выход — Hello World

Использование десериализации

В Java сериализация используется для преобразования текущего состояния объекта в поток байтов. десериализация является полной противоположностью, поскольку мы воссоздаем объект, используя поток байтов. Для процесса сериализации нам необходимо реализовать интерфейс Serializable.

Обработка исключений должна быть сделана для создания объектов с использованием этого метода.

Использование метода newInstance() класса Constructor

Мы увидели метод newInstance класса Class, который мы использовали для создания объекта. Точно так же конструктор класса также состоит из метода newInstance(), который можно использовать для создания объектов. Другие могут использовать конструкторы Java по умолчанию с помощью этого метода, мы также можем вызвать параметризованные конструкторы.

Welcome to the world of programming.

Это 5 различных способов создания объектов в Java, которые используются чаще других. Каждый метод имеет свои преимущества и недостатки. В конце концов, выбор за вами.

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *