如何在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");
}
}
答案 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
删除Object
。Integer[] c = a.gen1(); // this causes ClassCastException
。当然你需要知道数组的大小。
更新:
在您的新示例中,您可以在此处获得例外:
Object[]
因为您正在尝试将Integer[]
投射到Object[]
。不可能。
你得到的是Integer
,但包含Object[] c = a.gen1();
for(Object n:c){
Integer nn = (Integer) n;
}
个引用。所以你需要这样做:
n
这是好的,因为Integer
是ArrayList
但作为一般规则:如果需要收集参数化类型对象,只需使用class
。在您的示例中,您甚至没有实际{{1}}通过反射实例化数组,这是唯一明智的选择