Ответ
Глубокое копирование создает новый объект и рекурсивно копирует все поля, включая вложенные объекты, а не просто копирует ссылки на них.
Основные подходы:
-
Ручная реализация (через конструктор копирования или
clone()):public class Person { private String name; private Address address; // mutable объект // Конструктор глубокого копирования public Person(Person original) { this.name = original.name; this.address = new Address(original.address); // Копируем вложенный объект } // Или через переопределение clone() (менее предпочтительно) @Override protected Person clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = this.address.clone(); // Требует, чтобы Address тоже реализовывал Cloneable return cloned; } } -
Сериализация/десериализация:
import java.io.*; public static <T extends Serializable> T deepCopy(T object) throws IOException, ClassNotFoundException { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(object); out.flush(); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(byteIn); return (T) in.readObject(); }- Плюсы: Универсально для любых графов объектов.
- Минусы: Низкая производительность; все объекты в графе должны реализовывать
Serializable.
-
Использование библиотек (рекомендуется для сложных объектов):
- Apache Commons Lang:
SerializationUtils.clone(object)(требуетSerializable). - Jackson/Gson: Сериализация в JSON и обратная десериализация.
// Пример с Gson Gson gson = new Gson(); Person copy = gson.fromJson(gson.toJson(original), Person.class);
- Apache Commons Lang:
Выбор метода зависит от сложности объекта, требований к производительности и необходимости сериализуемости.
Ответ 18+ 🔞
А, ну это ж классика, блядь! Глубокое копирование, ёпта! Это когда ты не просто ссылку на ту же самую квартиру копируешь, а строишь новую, блядь, хрущёвку, со всеми потрохами, чтобы там свой бардак завести можно было, и в оригинале ничего не менялось. Не то что поверхностное, где вы оба за один хуй дергаетесь — там один поменял, второй охуел.
Ну, вариантов дохуя, как это провернуть:
-
Своими кривыми ручками, внатуре. Сам всё описываешь, как копировать.
public class Person { private String name; private Address address; // А это, сука, изменяемый объект, в нём тоже своя банда! // Конструктор для полного клонирования, чтоб всё было твоё public Person(Person original) { this.name = original.name; this.address = new Address(original.address); // Вот тут ключ, блядь! Не просто address, а НОВЫЙ address, скопированный! } // Или через этот ёбаный clone() (но его все не любят, честно) @Override protected Person clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = this.address.clone(); // И от адреса тоже требуешь клона, пидарас! return cloned; } }Работает, но если объектов как говна за баней — заебёшься каждый описывать, волнение ебать.
-
Через сериализацию — мощно, но тупо. Берёшь объект, превращаешь в поток байтов, а потом из этих байтов собираешь нового такого же уродца.
import java.io.*; public static <T extends Serializable> T deepCopy(T object) throws IOException, ClassNotFoundException { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(object); // Записал старого out.flush(); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(byteIn); return (T) in.readObject(); // Прочитал нового! Магия, блядь! }- Плюс: Хуярь хоть какие графы объектов, хоть циклические ссылки — всё скопирует, если они
Serializable. - Минус: Медленно, пиздец как медленно. И все, сука, должны быть
Serializable, а это не всегда так.
- Плюс: Хуярь хоть какие графы объектов, хоть циклические ссылки — всё скопирует, если они
-
Взять готовую банду (библиотеки). Самый разумный путь для сложных случаев.
- Apache Commons Lang:
SerializationUtils.clone(object). Красиво, но опять требуетSerializable, терпения ноль ебать. - Jackson/Gson: А это хитрая жопа! Превращаешь объект в JSON (как будто в текст его размазал), а потом из текста собираешь свеженькую копию.
// Gson, например Gson gson = new Gson(); Person copy = gson.fromJson(gson.toJson(original), Person.class); // И охуенно, и сериализуемость не нужна!
- Apache Commons Lang:
Короче, выбор, блядь, зависит от того, насколько у тебя всё запущено. Если объект простой — руками. Если граф большой и ебнутый — библиотека в помощь. А сериализация — это как молоток: универсально, но не всегда изящно. Думай головой, а не жопой!