问题
Possible Duplicate:
Java how to: Generic Array creation
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?
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.
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
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");
}
}
回答1:
1. Arrays
are Not Generic
2. Thats the reason Arrays
are checked during compile as well as runtime, where as Collections
can be Generic and its checked only during the compile time....
回答2:
(T[][]) new Object[size][size]
回答3:
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:
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
.
(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 same at runtime. So they don't have this problem.)
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).
<T extends MyBaseClass> T distribute() {
T answer = //...?
return answer;
}
I hope you can see why this is impossible.
回答4:
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.
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:
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
来源:https://stackoverflow.com/questions/12020527/how-to-create-generic-array