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");
}
} |
- 为什么你不能从一个ballsvarargs得到一个Class,假设有一个?不管怎样,你一定会听到"数组和泛型不能很好地结合在一起"的说法。
- 最简单的方法是不使用数组,使用某种类型的Collection。
1。Arrays不是Generic。
2。这就是在编译和运行时检查Arrays的原因,因为Collections可以是通用的,并且只能在编译时检查它。
- 所以,当只有一个慷慨的信息时,不可能创建一个类型的数组?
- 您可以使用类似于@SuppressWarnings("unchecked") B[] arr = new B[3];的东西,但您需要取消编译器警告….但是为什么在运行时不存在通用信息,而且当我在Java中工作时,我不喜欢使用数组。集合提供了更大的灵活性
- 对。或者更确切地说,您没有泛型信息开始,因为它在运行时被擦除(至少在纯Java中)。这是一个编译时特性,一旦应用程序运行,它就会完全丢失。
- @Sarcan Ya…这个过程称为Erasure,其中compiler removes the Type Parameter and Argument Parameters from the class , method, etc..。使其成为原始类型(原始类型是没有类型参数的泛型类或接口名称)
你的要求是不可能的。数组在运行时知道其组件类型,不同组件类型的数组是不同的运行时类型。这就是为什么在创建数组时,需要知道运行时的组件类型。
由于您的方法是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引用。所以你需要做的是:
这是正常的,因为n是Integer。但作为一般规则:如果需要收集参数化类型对象,只需使用ArrayList。在您的示例中,甚至没有实际的class通过反射来实例化数组,这是唯一明智的选择。
- 这不会导致运行时出现ClassCastException吗?
- 不,因为类型参数T将被编译器删除,并且无论如何都将被Object替换。这称为type-erasure。您正在将特定对象添加到Object数组中,这是合法的
- @如果您试图将其分配给T的具体类型,它将导致ClassCastException:String[] foo = foo(); public static T[] foo() { return (T[]) new Object[5]; }。
- @jeffrey@user384796我试过了,它引起了ClassCastException。我需要创建普通类型的普通数组。
- @DIMS:更新答案