Java | Фишки и трюки
7.21K subscribers
182 photos
29 videos
6 files
40 links
Java: примеры кода, интересные фишки и полезные трюки

Купить рекламу: https://telega.in/c/java_tips_and_tricks

✍️По всем вопросам: @Pascal4eg
Download Telegram
⌨️ Клонирование объектов

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

Класс Object содержит protected метод clone(), осуществляющий побитовое копирование объекта производного класса. Однако сначала необходимо переопределить метод clone() как public для обеспечения возможности его вызова. В переопределенном методе следует вызвать базовую версию метода super.clone(), которая и выполняет собственно клонирование.

Чтобы окончательно сделать объект клонируемым, класс должен реализовать интерфейс Cloneable. Интерфейс Cloneable не содержит методов относится к маркерным интерфейсам, а его реализация гарантирует, что метод clone() класса Object возвратит точную копию вызвавшего его объекта с воспроизведением значений всех его полей. В противном случае метод генерирует исключение CloneNotSupportedException. Следует отметить, что при использовании этого механизма объект создается без вызова конструктора.


public class MyClass implements Cloneable {
private int value;

// Конструкторы и методы класса

@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}


Это решение эффективно только в случае, если поля клонируемого объекта представляют собой значения базовых типов и их обёрток или неизменяемых (immutable) объектных типов. Если же поле клонируемого типа является изменяемым ссылочным типом, то для корректного клонирования требуется другой подход. Причина заключается в том, что при создании копии поля оригинал и копия представляют собой ссылку на один и тот же объект. В этой ситуации следует также клонировать и сам объект поля класса.

Такое клонирование возможно только в случае, если тип атрибута класса также реализует интерфейс Cloneable и переопределяет метод clone(). Так как, если это будет иначе вызов метода невозможен из-за его недоступности. Отсюда следует, что если класс имеет суперкласс, то для реализации механизма клонирования текущего класса-потомка необходимо наличие корректной реализации такого механизма в суперклассе. При этом следует отказаться от использования объявлений final для полей объектных типов по причине невозможности изменения их значений при реализации клонирования.

Помимо встроенного механизма клонирования в Java для клонирования объекта можно использовать:

✔️ Специализированный конструктор копирования - в классе описывается конструктор, который принимает объект этого же класса и инициализирует поля создаваемого объекта значениями полей переданного.

✔️ Фабричный метод - (Factory method), который представляет собой статический метод, возвращающий экземпляр своего класса.

✔️ Механизм сериализации - сохранение и последующее восстановление объекта в/из потока байтов.

#java #clone
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍5🔥1
⌨️ В чем отличие между поверхностным и глубоким клонированием?

Поверхностное копирование копирует настолько малую часть информации об объекте, насколько это возможно. По умолчанию, клонирование в Java является поверхностным, т.е. класс Object не знает о структуре класса, которого он копирует. Клонирование такого типа осуществляется JVM по следующим правилам:

✔️ Если класс имеет только члены примитивных типов, то будет создана совершенно новая копия объекта и возвращена ссылка на этот объект.

✔️ Если класс помимо членов примитивных типов содержит члены ссылочных типов, то тогда копируются ссылки на объекты этих классов. Следовательно, оба объекта будут иметь одинаковые ссылки.

Глубокое копирование дублирует абсолютно всю информацию объекта:

✔️ Нет необходимости копировать отдельно примитивные данные;

✔️ Все члены ссылочного типа в оригинальном классе должны поддерживать клонирование. Для каждого такого члена при переопределении метода clone() должен вызываться super.clone();

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

#java #clone
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥1
⚙️ Разница между deep copy и shallow copy

При копировании объектов в Java различают два типа копий:

Shallow copy – копирует только ссылки на вложенные объекты, изменения в одном объекте затронут копию.
Deep copy – создаёт полную копию, включая все вложенные объекты.

✔️ Пример shallow copy:


class Person implements Cloneable {
String name;

Person(String name) {
this.name = name;
}

public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}


Для создания полной копии можно использовать конструктор копирования или сериализацию/десериализацию.

✔️ Пример deep copy:


import java.io.*;

public class DeepCopyExample {
public static void main(String[] args) {
Person person = new Person("John", 30);
Person deepCopy = deepCopy(person);

System.out.println("Original: " + person.getName() + ", " + person.getAge());
System.out.println("Deep copy: " + deepCopy.getName() + ", " + deepCopy.getAge());
}

public static <T extends Serializable> T deepCopy(T object) {
try {
ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);
objectOutputStream.writeObject(object);

ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteOutputStream.toByteArray());
ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);
T copy = (T) objectInputStream.readObject();

return copy;
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
}

class Person implements Serializable {
private String name;
private int age;

public Person(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}
}


💡 Совет: Используйте deep copy, если объект содержит изменяемые вложенные объекты, иначе изменения в одном месте могут неожиданно повлиять на копию.

#java #deepcopy #shallowcopy #clone
Please open Telegram to view this post
VIEW IN TELEGRAM
👍91