Как реализовать поверхностное (shallow) копирование объекта в Java?

«Как реализовать поверхностное (shallow) копирование объекта в Java?» — вопрос из категории Java Core, который задают на 10% собеседований Java Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

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

Основные способы:

  1. Использование метода clone() (интерфейс Cloneable):

    class Person implements Cloneable {
        String name; // Ссылочное поле
        int age;     // Примитивное поле
    
        @Override
        public Person clone() throws CloneNotSupportedException {
            return (Person) super.clone(); // Вызов Object.clone()
        }
    }
    • Недостаток: Использование Cloneable и защищенного метода Object.clone() считается устаревшим подходом.
  2. Конструктор копирования:

    class Person {
        String name;
        int age;
    
        // Конструктор копирования
        public Person(Person other) {
            this.name = other.name; // Копируется ссылка
            this.age = other.age;   // Копируется значение
        }
    }
  3. Фабричный метод или статический метод копирования:

    public static Person shallowCopy(Person original) {
        Person copy = new Person();
        copy.name = original.name;
        copy.age = original.age;
        return copy;
    }

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