Заполнить массив клонами одного объекта - PullRequest
3 голосов
/ 20 февраля 2010

Что такое быстрый и простой способ заполнить массив Java клонами одного объекта?

например. после того, как:

Rectangle[] rectangles = new Rectangle[N];
fillWithClones(rectangles, new Rectangle(1, 2, 3, 4));

массив rectangles будет содержать N различных Rectangle экземпляров, инициализированных с одинаковыми координатами.

Я знаю о недостатках Object.clone() в Java, но в этом случае я знаю, что копируемые объекты имеют не бросающие, публичные clone() методы, но могут иметь или не иметь открытый конструктор копирования. 1012 *

Я предполагаю, что где-то есть метод библиотеки, который делает это, но я не думаю, что это в JDK, Commons-collection или Guava.

Ответы [ 4 ]

2 голосов
/ 20 февраля 2010

Если у вас нет определенного типа, с которым вы хотите работать во время компиляции, вам придется вызывать метод clone по отражению.

private static <T> T cloneByReflection(T object) {
    try {
        return (T) object.getClass().getMethod("clone").invoke(object);
    } catch (Exception e) {
        return null;    // or whatever you want to do
    }
}

public static <T> void fillWithClones(T[] array, T template) {
    for (int i = 0; i < array.length; ++i)
        array[i] = cloneByReflection(template);
}
0 голосов
/ 20 февраля 2010

Если конструктор копирования может существует (и вы хотите использовать его, если он есть), вы можете сделать что-то вроде этого:

(Редактировать: обновлен код для использования массива вместо List):

private static <T> void fillWithClones( T[] array, T object )
{
  try
  {
    @SuppressWarnings("unchecked")
    Class<T> clazz = (Class<T>)object.getClass();
    Constructor<T> c = clazz.getConstructor( object.getClass() );

    try
    {
      for ( int i = 0; i < array.length; i++ )
      {
        array[i] = (T)c.newInstance( object );
      }
    }
    catch ( Exception e )
    {
      // Handle exception or rethrow...
    }
  }
  catch ( NoSuchMethodException e )
  {
    // No copy constructor, try clone option...
  }
}

Конечно, часть обработки исключений может быть приведена в порядок.

0 голосов
/ 20 февраля 2010

@ Ответ Криса Джестера-Янга дает вам рецепт того, что вы хотите делать.

Но я бы предположил, что в приложении, которое делает подобные вещи, есть что-то не так.

  • Почему вашему приложению требуется для создания глубоких копий массивов случайных вещей? Если вы не знаете типы вещей, откуда вы знаете, что копирование необходимо?

  • Что должно делать ваше приложение, если массив содержит неклонируемый объект? Вы бросаете исключение? Вы помещаете null в массив, требующий более поздней проверки нуля?

Лучше проектировать, чтобы все объекты, которые вы хотите клонировать, реализовывали интерфейс с помощью (общедоступного) метода клонирования. Таким образом, вы можете иметь статически типизированное решение (без исключений динамического типа!) И избежать ненужных вызовов clone рефлексивно.

0 голосов
/ 20 февраля 2010

Для прямоугольников:

public void fillWithClones(Rectangle[] arr, Rectangle src) {
    for(int xa=0,len=arr.length; xa<len; xa++) { arr[xa]=(Rectangle)src.clone(); }
    }
...