Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Как скопировать объект

Короткий ответ

Самый понятный способ — конструктор копирования, который принимает объект того же класса:

class Settings {
    String theme;
    int fontSize;
 
    Settings(String theme, int fontSize) {
        this.theme = theme;
        this.fontSize = fontSize;
    }
 
    Settings(Settings other) {
        this(other.theme, other.fontSize);
    }
}
 
void main() {
    var original = new Settings("dark", 14);
    var copy = new Settings(original);
    copy.fontSize = 18;
 
    IO.println(original.fontSize + " " + copy.fontSize);
}

Результат:

14 18

Записи копировать не нужно

Неизменяемый объект можно использовать в нескольких местах без копий. Для «изменённой копии» создайте новый объект:

record Settings(String theme, int fontSize) {
    Settings withFontSize(int size) {
        return new Settings(theme, size);
    }
}
 
void main() {
    var original = new Settings("dark", 14);
    IO.println(original.withFontSize(18));
    IO.println(original);
}

Результат:

Settings[theme=dark, fontSize=18]
Settings[theme=dark, fontSize=14]

Глубокая копия

Если объект содержит изменяемый список, скопируйте и его, иначе обе копии будут делить один список:

class Playlist {
    String name;
    List<String> songs;
 
    Playlist(String name, List<String> songs) {
        this.name = name;
        this.songs = songs;
    }
 
    Playlist(Playlist other) {
        this(other.name, new ArrayList<>(other.songs));
    }
}
 
void main() {
    var original = new Playlist("Road", new ArrayList<>(List.of("Song A")));
    var copy = new Playlist(original);
    copy.songs.add("Song B");
 
    IO.println(original.songs);
    IO.println(copy.songs);
}

Результат:

[Song A]
[Song A, Song B]

Частая ошибка

Присвоить объект другой переменной. Это не копия: обе переменные указывают на один объект:

class Counter {
    int value;
}
 
void main() {
    var a = new Counter();
    var b = a;
    b.value = 10;
 
    IO.println(a.value);
}

Результат:

10

Метод clone() тоже существует, но работать с ним неудобно: нужен интерфейс Cloneable, приведение типа и обработка исключения. В новом коде используйте конструктор копирования или записи.

Функции из этого ответа

  • record — Объявляет запись — неизменяемый класс для хранения данных с готовыми equals(), hashCode() и toString().
  • List.copyOf() — Создаёт неизменяемую копию коллекции в виде списка.
  • Cloneable — Маркерный интерфейс, который разрешает Object.clone(). В новом коде вместо него используют копирующие конструкторы.

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.