Глубокое копирование массива объектов java
Как можно используя масссив объектов (собственных, не String, Integer и т.п.) скопировать его в другой массив вместе с копиями его полей? Я использую System.arraycopy у меня без проблем копируется второй массив, но проблема в том, что 2 разных массива ссылаются на одни и те же данные (одну и ту же область памяти), и ⇒ при изменении переменной в одном массиве - она изменяется и во втором. Как этого избежать? Пример:
public class MyClass {
public static void main(String args[]) {
Mas mas1 = new Mas();
mas1.num = 1;
Mas mas2 = new Mas();
mas2.num = 2;
Mas mas3 = new Mas();
mas3.num = 3;
Mas[] massiv = new Mas[3];
massiv[0] = mas1;
massiv[1] = mas2;
massiv[2] = mas3;
System.out.println(massiv[0].num + " " + massiv[1].num + " " + massiv[2].num);
Mas[] massiv2 = new Mas[3];
System.arraycopy(massiv, 0, massiv2, 0, 3);
System.out.println(massiv2[0].num + " " + massiv2[1].num + " " + massiv2[2].num);
massiv2[0].num = 4;
System.out.println(massiv[0].num + " " + massiv[1].num + " " + massiv[2].num);
System.out.println(massiv2[0].num + " " + massiv2[1].num + " " + massiv2[2].num);
}
}
class Mas {
int num;
}
Вывод:
1 2 3
1 2 3
4 2 3
4 2 3
Ответы (2 шт):
Вы должны скопировать каждый элемент массива. Вы не можете скопировать массив в целом. Возможно вы слышали термин "Deep Copy".
Вам понадобится цикл for, как бы это не было некрасиво. И уже в цикле скопировать каждый объект отдельно.
Нативный метод System.arraycopy не выполняет «Глубокого копирования» массива, также как и метод Arrays.copyOf. В новый массив копируются элементы из старого, т. е. ссылки на объекты. Глубокое копирование вложенных объектов, в т. ч. массивов, нужно реализовывать самостоятельно с учетом необходимой глубины копирования, также можно использовать сериализацию.
Пример алгоритма «Глубокого копирования» массива. В новый массив копируются не ссылки на элементы из исходного массива, а создаются новые объекты:
static class Element {
int num;
public Element(int num) {
this.num = num;
}
@Override
public String toString() {
return String.valueOf(num);
}
}
public static void main(String[] args) {
Element[] arr = new Element[3];
arr[0] = new Element(1);
arr[1] = new Element(2);
arr[2] = new Element(3);
Element[] arr2 = new Element[3];
IntStream.range(0, 3).forEach(i -> arr2[i] = new Element(arr[i].num));
arr2[0].num = 4;
System.out.println(Arrays.toString(arr)); // [1, 2, 3]
System.out.println(Arrays.toString(arr2)); // [4, 2, 3]
}