使用单个对象的克隆填充数组

时间:2010-02-20 01:40:03

标签: java arrays collections clone

使用单个对象的克隆填充Java数组的快速简便方法是什么?

e.g。后:

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

rectangles数组将包含N个不同的Rectangle个实例,并使用相同的坐标进行初始化。

我知道Java中Object.clone()的缺陷,但在这种情况下,我知道要复制的对象具有非抛出的公共clone()方法,但可能有也可能没有公开复制构造函数。

我猜这里有一个库方法可以做到这一点,但我不认为它存在于JDK,Commons-collections或Guava中。

4 个答案:

答案 0 :(得分:2)

如果您没有在编译时使用的特定类型,则必须通过反射调用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);
}

答案 1 :(得分:0)

对于矩形:

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

答案 2 :(得分:0)

@Chris Jester-Young给你一个做你想做的事情的方法。

但我建议应用程序执行此类操作时会出现一些错误。

  • 为什么您的应用需要来制作随机数组的深层副本?如果你不知道事物的类型,你怎么知道复制是必要的?

  • 当数组包含不可克隆的对象时,您的应用程序应该做什么?你抛出一个例外吗?你在数组中加了一个null,需要稍后进行空检查吗?

更好的设计是让您可能要克隆的所有对象都实现具有(公共)克隆方法方法的接口。这样你就可以得到一个静态类型的解决方案(没有动态类型异常!),你可以避免反复调用clone的开销。

答案 3 :(得分:0)

如果复制构造函数可能存在(如果有的话你想使用它),你可以这样做:

(编辑:更新了使用数组代替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...
  }
}

当然,有些异常处理可以整理。