关于java:如何创建通用数组?

How to create generic array?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Java how to: Generic Array creation

如何在Java中创建一个类型的EDCOX1×0的数组?我不能使用Arrays.newInstance(),因为我没有Class的对象。在某个地方是否有newInstance的通用版本?

我的方法原型如下:

1
2
3
4
5
6
7
8
public <T> T[][] distribute(T ... balls) {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

更新

很抱歉,在上面的例子中,我可以从balls上课。但是假设我没有这样的变量。

1
2
3
4
5
6
7
8
public <T> T[][] distribute() {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

1
2
3
4
5
6
7
8
9
10
11
class<T> {
   public T[][] distribute() {

      T[][] answer = ????

      // filling answer with data

      return answer;

   }
}

更新2

此示例也不起作用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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");

}

}


1。Arrays不是Generic

2。这就是在编译和运行时检查Arrays的原因,因为Collections可以是通用的,并且只能在编译时检查它。


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

由于您的方法是T上的泛型方法,调用方可以在每次调用此方法时向编译器指定它想要使用的T。所以想想这有多荒谬:

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

右边的编译代码对于这两行来说是相同的。.文件只是对编译器的提示,并不影响编译后的代码。因此,这意味着distribute()必须返回同时为String[][]Integer[][]的内容(然后在运行时进行检查,因为String[][]Integer[][]是重新定义的运行时类型)。唯一能满足这个要求的值是null

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

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

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

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


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


do:T[][] answer = (T[][]) new Object[][];T将被编译程序删除到Object。当然,您需要知道数组的大小。

更新:在您的新示例中,您将在此处获得异常:Integer[] c = a.gen1(); // this causes ClassCastException因为你想把一个Object[]投射到一个Integer[]上。不可能。您得到的是一个Object[],但包含Integer引用。所以你需要做的是:

1
2
3
4
Object[] c = a.gen1();
for(Object n:c){  
    Integer nn = (Integer) n;  
}

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