Java继承器数组构造和协变返回

时间:2011-11-23 18:41:30

标签: java arrays gwt instantiation subtype

(标题听起来有点过于花哨,但我找不到匹配,所以我们希望它是描述性的。)

我有一段如下工作代码:

@SuppressWarnings("unchecked")
public static Copyable[] copyOf(Copyable[] objects, Class type) {
    Copyable[] copies = Arrays.copyOf(objects, objects.length, type);
    for( int i=0; i < copies.length; ++i ) {
        if( objects[i] == null )
            throw new IllegalArgumentException("Copyable[] contains null reference", new NullPointerException());
        copies[i] = objects[i].copy();
    }

    return copies;
}

不像我想的那样漂亮,因为我必须传入数组类,但它适用于我想要它做的事情:分配一个可复制实现者的新数组并使用实现的方法填充它。

我遇到的问题是这是由GWT编译的,它的JRE Emulation库barfs在正确的Java上没有实现。我需要在不调用Arrays.copyOf()的情况下这样做,希望没有反射。

注意:我正在研究clone()版本,但实际上并不想依赖于clone()。我觉得必须有一个更清洁的解决方案。

5 个答案:

答案 0 :(得分:2)

这个怎么样:

public static Copyable[] copyOf(Copyable[] objects) {
    Copyable[] copies = new Copyable[objects.length];
    for( int i=0; i < copies.length; ++i ) {
        if( objects[i] == null )
            throw new IllegalArgumentException("Copyable[] contains null reference", new NullPointerException());
        copies[i] = objects[i].copy();
    }
    return copies;
}

在复制元素本身之前,无需将objects数组实际复制到copies

修改

如果您的可复制对象是可序列化的,则可以序列化然后反序列化数组以创建副本。 gwt-test-utils中有一个实用函数DeepCopy.java,可以完全满足你的需要。

答案 1 :(得分:1)

为什么你不能这样做: Copyable[] copies = new Copyable[objects.length];? 该行分配了数组,然后你已经用你所包含的for循环填充它。

答案 2 :(得分:1)

也许与泛型:

public interface Copyable<T> {
  T copy();
}



import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

public class Test {
  static class My implements Copyable<My> {
    int x;

    public My copy() {
      My my = new My();
      my.x = this.x;
      return my;
    }
  }

  @SuppressWarnings("unchecked")
  public static <T extends Copyable<T>> T[] copyOf(T[] objects, Class<T> type) {
    List<T> copies = new ArrayList<T>();
    for (int i = 0; i < objects.length; ++i) {
      if (objects[i] == null) throw new IllegalArgumentException("Copyable[] contains null reference",
          new NullPointerException());
      copies.add((T) objects[i].copy());
    }
    T typeVar = null;
    try {
      typeVar = (T) Class.forName(type.getName()).newInstance();
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    Object t = Array.newInstance(typeVar.getClass(),0);
    return copies.toArray((T[])t); 
  }

  public static void main(String[] args) {
    My[] stuff = new My[1];
    My elem = new My();
    elem.x = 1;
    stuff[0] = elem;
    My[] copies = copyOf(stuff, My.class);
    System.out.println(copies[0].x);
  }
}

答案 3 :(得分:0)

GriffeyDog's answersome fun I had with generics recently上构建,这是一个没有直接在数组上工作的Class个对象的解决方案:

@SuppressWarnings("unchecked")
public static <T extends Copyable> T[] copyOf(T[] objects) {
    T[] copies = (T[]) new Object[objects.length];
    for (int i = 0; i < copies.length; ++i) {
        if (objects[i] == null)
            throw new IllegalArgumentException(/*...*/);
        copies[i] = (T) objects[i].copy();
    }
    return copies;
}

答案 4 :(得分:0)

您可以依靠clone()来获取数组本身,然后对每个对象使用copy()

@SuppressWarnings("unchecked")
public static Copyable[] copyOf(Copyable[] objects) {
    Copyable[] copies = (Copyable[]) objects.clone();
    for( int i=0; i < copies.length; ++i ) {
        if( objects[i] == null )
            throw etc;
        copies[i] = objects[i].copy();
    }
    return copies;
}

每个数组都实现了clone()方法,该方法返回数组的浅表副本。所以我认为它足够干净,满足您的需求。

请注意,这样,您也不需要参数Class type