java 如何创建通用数组?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12020527/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to create generic array?
提问by Dims
Possible Duplicate:
Java how to: Generic Array creation
可能的重复:
Java 如何:通用数组创建
How to create an array of type T[]
in Java? I can't use Arrays.newInstance()
since I have no objects of Class<T>
. Is there a generic version of newInstance
somewhere?
如何T[]
在Java中创建类型数组?我无法使用,Arrays.newInstance()
因为我没有Class<T>
. newInstance
某处有通用版本吗?
My method prototype follows:
我的方法原型如下:
public <T> T[][] distribute(T ... balls) {
T[][] answer = ????
// filling answer with data
return answer;
}
UPDATE
更新
Sorry in example above I can take class from balls
. But suppose I have no such a variable.
抱歉,在上面的示例中,我可以从balls
. 但是假设我没有这样的变量。
public <T> T[][] distribute() {
T[][] answer = ????
// filling answer with data
return answer;
}
or
或者
class<T> {
public T[][] distribute() {
T[][] answer = ????
// filling answer with data
return answer;
}
}
UPDATE2
更新2
This example also does not work:
这个例子也不起作用:
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");
}
}
回答by Kumar Vivek Mitra
1.Arrays
are NotGeneric
1.Arrays
是不是Generic
2.Thats the reason Arrays
are checked during compile as well as runtime, where as Collections
can be Genericand its checked only during the compile time....
2.那原因Arrays
是编译时检查,以及运行时,那里的Collections
可通用且其仅在编译期进行检查....
回答by newacct
What you ask is not possible. An array knows its component type at runtime, and arrays of different component types are different runtime types. That's why when you create the array, you need to know the component type at runtime.
你问的是不可能的。一个数组在运行时就知道它的组件类型,不同组件类型的数组是不同的运行时类型。这就是为什么在创建数组时,需要在运行时知道组件类型的原因。
Since your method is generic over T
, the caller can dictate the T
it wants to use to the compiler every time it calls this method. So consider how absurd this is:
由于您的方法是泛型的T
,因此T
每次调用此方法时,调用者都可以向编译器指示它要使用的内容。所以想想这是多么荒谬:
String[][] foo = this.<String>distribute();
Integer[][] bar = this.<Integer>distribute();
The compiled code on the right side of this is identical for the two lines. The .<String>
stuff is just hints to the compiler, and do not affect the compiled code. So this means that distribute()
must return something that is both String[][]
and Integer[][]
(which is then checked at runtime, since String[][]
and Integer[][]
are reified runtime types). The only value that can satisfy this is null
.
这两行右侧的编译代码是相同的。这些.<String>
东西只是给编译器的提示,不会影响编译后的代码。所以这意味着distribute()
必须返回既是String[][]
and 的东西Integer[][]
(然后在运行时检查,因为String[][]
andInteger[][]
是具体的运行时类型)。唯一能满足这一点的值是null
。
(You might ask, why does this problem not occur for methods that return List<T>
? The answer is that, unlike for arrays, there is only one class List
at runtime. And lists do not know their component types at runtime. So a new ArrayList<Foo>()
and a new ArrayList<Bar>()
are exactly the sameat runtime. So they don't have this problem.)
(也许你会问,为什么不提供方法出现此问题的回报List<T>
呢?答案是,不像数组,只有一类List
在运行时,并列出不要在运行时知道自己的组件类型,所以一new ArrayList<Foo>()
和new ArrayList<Bar>()
是完全相同在运行时相同。所以他们没有这个问题。)
Another analogy of what is happening here: So array types have an inheritance pattern that follows the inheritance of their component types. So Integer[][]
is a subclass of Object[][]
. And in fact, all T[][]
are subclasses of Object[][]
. So instead of Object[][]
and its subclasses, let's consider a non-array class, MyBaseClass
, which has a bunch of subclasses. Then, what you are basically asking is to be able to generically create an instance of an unknown subclass of MyBaseClass
(determined by a type parameter).
这里发生的事情的另一个类比:因此数组类型具有遵循其组件类型继承的继承模式。所以,Integer[][]
是的子类Object[][]
。事实上,所有T[][]
都是Object[][]
. 因此Object[][]
,让我们考虑一个非数组类,而不是它的子类MyBaseClass
,它有一堆子类。然后,您基本上要求的是能够一般地创建未知子类的实例MyBaseClass
(由类型参数确定)。
<T extends MyBaseClass> T distribute() {
T answer = //...?
return answer;
}
I hope you can see why this is impossible.
我希望你能明白为什么这是不可能的。
回答by Amit Deshpande
(T[][]) new Object[size][size]
(T[][]) new Object[size][size]
回答by Cratylus
Do: T[][] answer = (T[][]) new Object[][];
T
will be erased anyway by compiler to Object
. Of course you need to know the size of the array.
Do:T[][] answer = (T[][]) new Object[][];
T
无论如何都会被编译器擦除到Object
. 当然你需要知道数组的大小。
Update:
In your new example you get the exception here:Integer[] c = a.gen1(); // this causes ClassCastException
Because you are trying to cast an Object[]
to an Integer[]
. Not possible.
What you get back is an Object[]
but containing Integer
references. So you would need to do:
更新:
在您的新示例中,您会在这里遇到异常:Integer[] c = a.gen1(); // this causes ClassCastException
因为您正在尝试将 anObject[]
转换为Integer[]
. 不可能。
你得到的是一个Object[]
但包含Integer
引用。所以你需要这样做:
Object[] c = a.gen1();
for(Object n:c){
Integer nn = (Integer) n;
}
This is ok since n
is an Integer
.
But as a general rule: If you need to collect parameterized type objects, simply use an ArrayList
. In your example where you don't even have the actual class
to instantiate the array via reflection it is the only sensible choice
这没关系,因为n
是一个Integer
.
但作为一般规则:如果您需要收集参数化类型的对象,只需使用ArrayList
. 在您甚至没有实际class
通过反射实例化数组的示例中,这是唯一明智的选择