What's left of this line after type erasure? (If E is
erased to object then I understand where the class
cast exception comes from)
That's exactly the problem: "new E[...]" gives an
Object[] if E is a type variable. We're aware of the
problem and are currently looking at a number of
different solutions to it, one of which is disallowing
"new E[...]".
-- Christian
Christian,
You don't have to disallow it
A possible solution was hinted at here http://forum.java.sun.com/thread.jsp?forum=316&thread=359061#1514591
but the need is now greater.
To reiterate (and update to Generics EA release 2)
For the rare cases where type parameters need to be known inside an instance, we add a "special" constructor signature, that the compiler can recognise, and at runtime this constructor is then passed the reflected type parameters from the "new" expression.
JSR175 might be usefully employed to indicate to the compiler that runtime type parameters should be passed.
The (possible) advent of the varargs stuff, suggests another syntax using a similar ... .
This in essence adds syntactic sugar to the obvious solution, which is to pass a Class or Type in the constructor
new ArrayList<String>(String.class)
so new ArrayList<String>.toArray() can return a String[] not an Object[].
Same could be applied for generic methods.
Some examples
new Widget<String>(5)
could be made to invoke a constructor with one of the following signatures (if it existed), or the normal Widget(int size) one otherwise.
Possible Type parameter aware constructor signatures / syntax
Widget(Type[] typeargs,int size){}
//familiar but maybe problematic
or
Widget(Type[] typeargs...,int size) {}
//maybe ambiguous in case when no "normal" parameters
or
Widget(Type[] ...typeargs,int size) {}
// ...
name means type parameter args and
// type must be "Type[]", must be 1st parameter.
//
name... means normal var args and must be last.
or
Widget(Type[],int size) @java.lang.TypeParameterAware() {}
// uses probable JSR175 syntax (as far as I can glean)!!
or
Widget<typeargs>(int size) {}
// but doesn't specify the Type of the parameter typeargs
// but the type will always be Type[]
or
Widget<Type[] typeargs>(int size) {}
// possibly the best
or
Widget<Type[] typeargs...>(int size) {}
// for consistency because it is matched by a syntactic list of types
// not by a Type[] expression.
[/code]
and similarly for parametric methods
/* non generic code calls this one */
public Object[] dongle(int size) {
return new Object[size];
}
/** type safe generic array constructor*/
public <A> A[] dongle<Type[] typeargs>(int size) {
return java.lang.reflect.Array.newInstance(typeargs[0],size);
}
I think all the above syntaxes could possibly work in terms of parsing (but I'm no expert). However I like the ...
name and <Type[]
name> syntaxes the most.
When the compiler is resolving which constructor to invoke, preference would be given to one expecting type parameters, and in the absence of one of those (which would in fact be the normal case), then match as per currently.
This will yield run time Type knowledge when required (and the toArray() problem in this thread is a case in point), without imposing runtime overhead on the majority of generic classes which don't need it.
Bruce