Java: передать массив ссылок? - PullRequest
0 голосов
/ 19 декабря 2010

У меня есть массив коллекций объектов, и я передаю эту ссылку методу, и метод выполняет некоторую бизнес-логику и обновляет объекты, чтобы они отражались в исходном объекте, поскольку я передаю его как ссылку. Теперь мой вопрос заключается в том, как избежать этого обновления исходного объекта.

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

Thx

Ответы [ 4 ]

4 голосов
/ 19 декабря 2010

Ваша ситуация немного сложна:

У вас есть массив ссылок на объекты.

Java всегда передается по значению, поэтому при передаче ссылки на массив в метод, ссылка на массив передается по значению.

Таким образом, метод имеет новую ссылку на тот же массив, что и область вызова.

Ответ на ваш вопрос: если вы не хотите, чтобы изменения отражались в объектах, вынужно скопировать объекты.Итак, для этого.

  1. У вас есть массив ссылок на объекты.
  2. Вы хотите выполнить некоторую работу на основе объектов, но не хотите изменять объекты.
  3. Вам следует создать массив объектов - объекты в этом массиве являются копиямиоригинального массива.
  4. Под «копией» я НЕ подразумеваю просто сделать копию объекта = оригинал.Вам нужно будет создать новый объект, который является копией.Было бы неплохо иметь метод getCopy () в соответствующем классе, который создает копии экземпляра.Это может быть сложно, если у ваших Объектов есть дочерние элементы или они содержат другие объекты.
  5. Вы передаете массив копий в метод, который выполняет эту работу.
3 голосов
/ 19 декабря 2010

Если вы хотите, чтобы исходные объекты оставались без изменений, вам необходимо внести изменения в копии исходных объектов. Это подразумевает «глубокую копию» массива, в которой вы не просто создаете второй массив со ссылками на те же объекты, но и делаете копии каждого объекта в массиве.

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

0 голосов
/ 19 декабря 2010

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

  • Сделайте копию объекта и передайте копию. Существует множество способов копирования объектов. Конструкторы копирования и статические фабричные методы, вероятно, лучше, чем реализация clone().
  • Создайте класс-оболочку только для чтения для класса объекта, создайте его экземпляр и передайте его. Оболочка только для чтения либо не предоставляет методы обновления, либо реализует их, ничего не делая, либо генерирует исключения.
  • Выполните рефакторинг API объекта, чтобы он имел интерфейс только для чтения и интерфейс чтения-записи, и передайте его как экземпляр первого. (Конечно, вызывающий может попытаться привести его к последнему ...)
  • Использование безопасности Java для предотвращения нежелательных обновлений. (Это дорого и сложно ...)

Конечно, если объект, который вы пытаетесь «защитить», имеет глубокую структуру, в которую вы хотите предотвратить изменения, тогда вам нужно убедиться, что вы справляетесь с этим; например путем глубокого копирования, путем возврата копий компонентов или возврата их в обертке и т. д.

Большинство вышеперечисленных подходов увеличивают сложность и затраты времени выполнения, поэтому я советую избегать конструкций, в которых требуется для выполнения подобных задач. Если это возможно, просто задокументируйте, что объект должен обрабатываться только для чтения, и оставьте это на усмотрение человека, который кодирует метод, чтобы делать правильные вещи.

Например, общеизвестно, что вы не должны изменять состояние объекта, используемого в качестве ключа в Map, таким образом, чтобы его значение изменялось. Однако, обычно ничего не делают, чтобы попытаться «навязать» это; то есть использовать изменяемые объекты в качестве ключей ... и просто не изменять их.

0 голосов
/ 19 декабря 2010

Вы можете использовать Collections.copy(dest, src), это сделает глубокую копию вашего массива.Но, из-за ошибки в методе, вы должны сделать несколько уловок:

//Assuming, that src is an array

List<Integer> src2 = Arrays.asList(src)

List<Integer> dest = new ArrayList<Integer>(src2);

Collections.copy(dest, src2);

На самом деле вам не нужно передавать исходный массив для создания массива destiantion.Вы должны передать массив того же размера, что и исходный массив.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...