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(); }
}
精彩评论