开发者

Fill an array with clones of a single object

What is a quick and easy way to fill a Java array with clones of a single object?

e.g. after:

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

the rectangles array would contain N distinct Rectangle instances, initialised with the same coordinates.开发者_运维问答

I am aware of the flaws of Object.clone() in Java, but in this case I know that the objects to be copied have non-throwing, public clone() methods but may or may not have a public copy constructor.

I'm guessing there is a library method somewhere that does this, but I don't think it's in the JDK, Commons-collections or Guava.


If you don't have the specific type you want to work with at compile time, you will have to invoke the clone method by reflection.

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);
}


@Chris Jester-Young answer gives you a recipe for doing what you want to do.

But I'd suggest that there is something rather wrong about an application that does this sort of thing.

  • Why does your application need to make deep copies of arrays of random things? If you don't know the things' types, how do you know that copying is necessary?

  • What is your application supposed to do when the array contains a non-clonable object? Do you throw an exception? Do you put a null in the array, requiring later null checking?

It is better design to have all of the objects that you may want to clone implement an interface with a (public) clone method method. That way you can have a statically typed solution (no dynamic type exceptions!) and you can avoid the overheads of invoking clone reflectively.


If a copy constructor might exist (and you want to use it if it does), you could do something like this:

(Edit: Updated code to use an array instead of 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...
  }
}

Some of the exception handling could be tidied up, of course.


For rectangles:

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜