如何创建通用数组?

时间:2012-08-18 17:04:32

标签: java arrays generics instantiation

  

可能重复:
  Java how to: Generic Array creation

如何在Java中创建类型T[]的数组?我无法使用Arrays.newInstance(),因为我没有Class<T>的对象。某处有newInstance的通用版本吗?

我的方法原型如下:

public <T> T[][] distribute(T ... balls) {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

更新

对不起上面的示例我可以从balls上课。但是假设我没有这样的变量。

public <T> T[][] distribute() {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

class<T> {
   public T[][] distribute() {

      T[][] answer = ????

      // filling answer with data

      return answer;

   }
}

UPDATE2

此示例也不起作用:

public abstract class GenericArray<T> {

abstract public T create();

public T[] gen1() {
    T[] ans = (T[]) new Object[3];
    ans[0] = create();
    ans[1] = create();
    ans[2] = create();
    return ans;
}

public Integer[] gen2() {
    Integer[] ans = new Integer[3];
    ans[0] = new Integer(0);
    ans[1] = new Integer(0);
    ans[2] = new Integer(0);
    return ans;
}

public static void main(String[] args) {

    GenericArray<Integer> a = new GenericArray<Integer>() {

        @Override
        public Integer create() {
            return new Integer(0);
        }
    };

    Integer[] b = a.gen2();
    Integer[] c = a.gen1(); // this causes ClassCastException

    System.out.println("done");

}

}

4 个答案:

答案 0 :(得分:6)

1。 Arrays Generic

2。这是Arrays在编译期间检查以及运行时的原因,其中Collections可以是 Generic < / strong>和仅在编译期间检查 ....

答案 1 :(得分:1)

(T[][]) new Object[size][size]

答案 2 :(得分:1)

你问的是不可能的。数组在运行时知道其组件类型,不同组件类型的数组是不同的运行时类型。这就是为什么在创建数组时,需要在运行时知道组件类型。

由于您的方法在T上是通用的,因此调用者可以在每次调用此方法时指示它要用于编译器的T。所以考虑一下这是多么荒谬:

String[][] foo = this.<String>distribute();
Integer[][] bar = this.<Integer>distribute();

右侧的编译代码对于两行是相同的。 .<String>内容只是编译器的提示,不会影响编译代码。所以这意味着distribute()必须返回同时为String[][]Integer[][]的内容(然后在运行时检查,因为String[][]Integer[][]是已确定的运行时类型)。唯一可以满足此值的是null

(您可能会问,为什么返回List<T>的方法不会出现此问题?答案是,与数组不同,运行时只有一个类List。并且列表不会在运行时知道它们的组件类型。因此new ArrayList<Foo>()new ArrayList<Bar>() 在运行时完全相同。因此它们没有这个问题。)

此处发生的事情的另一个类比:因此,数组类型具有继承模式,该模式遵循其组件类型的继承。所以Integer[][]Object[][]的子类。事实上,所有T[][]都是Object[][]的子类。因此,不要使用Object[][]及其子类,而是考虑一个非数组类MyBaseClass,它有一堆子类。然后,您基本上要求的是能够一般地创建MyBaseClass的未知子类的实例(由类型参数确定)。

<T extends MyBaseClass> T distribute() {
    T answer = //...?
    return answer;
}

我希望你能明白为什么这是不可能的。

答案 3 :(得分:0)

执行:T[][] answer = (T[][]) new Object[][];
无论如何编译器将T删除ObjectInteger[] c = a.gen1(); // this causes ClassCastException。当然你需要知道数组的大小。

更新:
在您的新示例中,您可以在此处获得例外:
Object[]
因为您正在尝试将Integer[]投射到Object[]。不可能。
你得到的是Integer,但包含Object[] c = a.gen1(); for(Object n:c){ Integer nn = (Integer) n; } 个引用。所以你需要这样做:

n

这是好的,因为IntegerArrayList 但作为一般规则:如果需要收集参数化类型对象,只需使用class。在您的示例中,您甚至没有实际{{1}}通过反射实例化数组,这是唯一明智的选择