Глубокая копия массива объектов
Я хочу сделать глубокую копию массива объектов, используя конструктор.
public class PositionList { private Position[] data = new Position[0]; public PositionList(PositionList other, boolean deepCopy) { if (deepCopy){ size=other.getSize(); data=new Position[other.data.length]; for (int i=0;i<data.length;i++){ data[i]=other.data[i]; }
Однако то, что у меня выше по какой-то причине, не работает. У меня есть автоматические тесты, которые я запускаю, и его провал этих тестов. Таким образом, theres ошибка здесь, что я не уверен, что это такое.
- Что делает объект jQuery отображаться как массив в инструментах разработчика Chrome?
- Случайная перетасовка массива
- Ошибка создания общего массива
- JSON Array итерация в Android / Java
- Эффективность: массивы против указателей
- Можно ли использовать новое место для массивов в переносном режиме?
- Есть ли способ мгновенно генерировать массив, заполненный диапазоном значений в Swift?
- Lambda выражение для преобразования массива / Список строк в массив / Список целых чисел
- Чтение вывода команды в массив в Bash
- Создание массива из диапазона в VBA
- Преобразование массива объектов в массив их примитивных типов
- Можно ли рассматривать 2D-массив как непрерывный массив 1D?
- Возвращаемый массив в функции
То, что вы реализовали, является мелкой копией. Чтобы выполнить глубокую копию, вы должны изменить
data[i] = other.data[i];
к некоторой вещи, которая назначает копию other.data[i]
data[i]
. Как вы это делаете, это зависит от classа Position
. Возможными альтернативами являются:
-
конструктор копирования:
data[i] = new Position(other.data[i]);
-
заводской метод:
data[i] = createPosition(other.data[i]);
-
клон:
data[i] = (Position) other.data[i].clone();
Заметки:
- Вышеизложенное предполагает, что конструктор копирования, фабричный метод и метод клона соответственно реализуют «правильный» вид копирования в зависимости от classа Position; Смотри ниже.
- Подход
clone
будет работать, только еслиPosition
явно поддерживает его, и это обычно рассматривается как низшее решение. Кроме того, вам нужно знать, что встроенная реализацияclone
(то есть методObject.clone()
) делает мелкую копию.
На самом деле общая проблема реализации глубокого копирования в Java сложна. В случае classа Position
можно предположить, что атрибуты являются всеми примитивными типами (например, ints или double), и поэтому глубокое или мелкое копирование является спорным. Но если есть ссылочные атрибуты, тогда вам нужно полагаться на метод конструктора / фабричного метода копирования / клонирования, чтобы выполнить требуемый тип копирования. В каждом случае его необходимо запрограммировать. И в общем случае (где вам приходится иметь дело с циклами) это сложно и требует, чтобы каждый class применял специальные методы.
Существует еще один возможный способ копирования массива объектов. Если объекты в массиве сериализуемы , их можно скопировать с помощью ObjectOutputStream
и ObjectInputStream
а затем десериализовать массив. Однако:
- это дорого,
- он работает только в том случае, если объекты (транзитивно) сериализуемы и
- значения любых полей
transient
не будут скопированы.
Копирование по сериализации не рекомендуется. Было бы лучше поддержать клонирование или какой-либо другой метод.
В целом, на Java лучше избегать глубокого копирования.
Наконец, чтобы ответить на ваш вопрос о конструкторах экземпляров classов classов, я ожидаю, что это примерно так:
public class Position { private int x; private int y; ... public Position(Position other) { this.x = other.x; this.y = other.y; } ... }
Как говорит @Turtle, нет никакой магии. Вы реализуете конструктор (вручную), который инициализирует его состояние, копируя из существующего экземпляра.
Когда ты говоришь:
data[i]=other.data[i];
Вы просто копируете список ссылок (предполагая, что это массив объектов). Если вы хотите сделать глубокую копию, вам нужно использовать new
для создания нового экземпляра каждого объекта в массиве.
Вместо того, чтобы говорить:
data[i]=other.data[i]
Вы захотите создать конструктор копирования для Position
(другими словами, конструктор для позиции, который принимает другую Position
и копирует примитивные данные внутри него) и говорят data[i]=new Position(other.data[i]);
В основном ваш конструктор «глубокой копии» PositionList
является конструктором копирования, хотя конструктор копирования имеет тенденцию указывать глубокую копию, поэтому параметр deepCopy
не нужен.
Вот функция, которую я использую:
function copy(arr) { return arr .map(x => Object .keys(x) .reduce((acc, y) => { acc[y] = x[y] return acc }, {})) }
Он работает только с массивами с объектами с одним уровнем.
Это должно сделать «глубокую» копию
int [] numbers = { 2, 3, 4, 5}; int [] numbersClone = (int[])numbers.clone();