Копирование и clone()

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

КопияЧто происходит с полями-ссылками
shallowссылки копируются, вложенные объекты общие
deepнужный граф объектов копируется рекурсивно

Механизм Object.clone

Cloneable — маркерный интерфейс без метода clone. Защищённый Object.clone() делает поразрядную shallow-копию полей и бросает CloneNotSupportedException, если класс не реализует Cloneable. Конструкторы при этом не вызываются.

final class Draft {
    private final String title;
    private final List<String> lines;
 
    Draft(String title, List<String> lines) {
        this.title = title;
        this.lines = new ArrayList<>(lines);
    }
 
    Draft(Draft source) { // явный copy constructor
        this(source.title, source.lines);
    }
}

В прикладном коде copy constructor или именованная фабрика обычно лучше clone: виден контракт, можно проверить инварианты и выбрать глубину копии.

Draft copy = new Draft(original);

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

Почему сериализация — плохой универсальный clone

Она медленнее, требует сериализуемости всего графа, связывает копирование с форматом и может выполнять небезопасную десериализацию. JSON round-trip также меняет типы/идентичность и скрывает контракт.

Ошибки

  • назвать копию deep, скопировав только список, но не его изменяемые элементы;
  • использовать clone() в наследуемом классе без продуманного контракта;
  • забыть про циклы и общие ссылки внутри графа;
  • копировать entity ORM и случайно переносить идентификатор/служебное состояние.

На собеседовании

Что делает Object.clone()? Shallow-копию полей без вызова конструктора.

Зачем Cloneable, если в нём нет методов? Это разрешающий маркер для Object.clone().

Копирует ли ArrayList.clone() элементы? Нет, копируется структура списка и ссылки на элементы.

Что предпочесть в доменной модели? Явный copy constructor/фабрику с описанной семантикой.

Связано: Сериализация и клонирование, Immutable классы и данные.