Клонирование объектов
Клонирование — создать копию объекта, а не просто скопировать ссылку. Обычное присваивание копирует ссылку, а не объект:
Point a = new Point(1, 2);
Point b = a; // b — это та же ссылка, не копия!
b.setX(99);
a.getX(); // 99 — изменили "b", а пострадал и a
Чтобы получить независимую копию, нужно явно клонировать — самый простой и безопасный способ в современной Java — копирующий конструктор:
class Point {
int x, y;
Point(int x, int y) { this.x = x; this.y = y; }
Point(Point other) { this(other.x, other.y); } // копирующий конструктор
}
Point a = new Point(1, 2);
Point b = new Point(a); // настоящая независимая копия
b.x = 99;
a.x; // всё ещё 1 — a не пострадал
Копнуть глубже
Поверхностное (shallow) vs глубокое (deep) клонирование. Если у объекта есть поля-ссылки на другие изменяемые объекты, простое копирование полей копирует только ссылки, а не вложенные объекты:
class Team {
List<String> members;
}
Team copy = new Team();
copy.members = original.members; // ❌ shallow — общий список на двоих!
copy.members.add("Хакер"); // испортит и original тоже
Team deepCopy = new Team();
deepCopy.members = new ArrayList<>(original.members); // ✅ deep — независимая копия списка
Чем глубже вложенность объектов, тем больше уровней нужно скопировать для настоящей независимости.
Встроенный Object.clone() — обычно лучше избегать. В Java есть интерфейс Cloneable и метод clone(), но у него плохая репутация: он не вызывает конструктор, по умолчанию делает только shallow-копию, и легко получить неожиданное поведение. Большинство Java-разработчиков сегодня предпочитают копирующий конструктор или статический фабричный метод — они явные и предсказуемые.
• разницу между поверхностным и глубоким клонированием (если дошёл до 2-го слоя).