Как скопировать объект
Короткий ответ
Самый понятный способ — конструктор копирования, который принимает объект того же класса:
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(). В новом коде вместо него используют копирующие конструкторы.