Reputation: 4469
On Java revisited ,a code excerpt goes below:
class Holder<T>{
private T[] contents;
private int index = 0;
public Holder(int size){
//contents = new T[size]; //compiler error - generic array creation
contents = (T[]) new Object[size]; //workaround - casting Object[] to generic Type
}...}
It is for generic array creation, but according to type erasure (I checked it on java online tutorial), T
ends into Object
at class compiled, so the cast (T[])
would ends into
(Object[])
, and that seems take no difference to without casting.
So what is the function of that casting or any special meaning for casting? any hint is thankful.
Upvotes: 2
Views: 187
Reputation: 213223
The cast is required to tell the compiler that the assignment is Ok from our side. Else it will show you compiler error.
Due to type erasure, the type parameter T
is replaced with it's erasure at compile time.
The erasure of an unbounded type parameter is Object
, whereas the erasure of the bounded type parameter is the type denoting the upper bound. So, if your type parameter in class had an upper bound - Holder<T extends Number>
, then the erasure of T
will be Number
. That means, T
will be replaced with Number
by the compiler.
So, in this case, since T
in unbounded, its erasure is Object
. So, it is replaced with Object
by the compiler.
Even though the casting removes the compiler error, the compiler would still show you a warning of Unchecked Cast. Because, the cast is not type safe, and would fail at runtime with ClassCastException
in case you instantiate the generic type using String
type parameter.
Try this:
Holder<String> stringHolder = new Holder<>(5);
String[] contents = stringHolder.getContents(); // ClassCastException
A safer way to create generic array is using Array.newInstance
method. You need to pass Class<T>
parameter to your constructor, and then use the following code:
public Holder(int size, Class<T> clazz){
contents = (T[]) Array.newInstance(clazz, size);
}
Here also you will see the Unchecked Cast
warning. But that is harmless.
Even safer way is not at all to create a array whose component type is a type parameter. You can rather use an ArrayList<T>
instead.
Reference:
Upvotes: 4
Reputation: 7799
If you consider that after type erasure all type parameters end up as simple Object
s, your question is about the use of Java Generics as a whole. In my opinion, these are:
Unfortunately, it was difficult to fit Generics in Java maintaining full backwards compatibility and other objectives at that point. The result is that new T[size]
is invalid. The only alternative is new Object[size]
. The cast (T[])
is to tell the compiler and other developers that that's exactly what you intended. In particular, the compiler will not emit a warning message in this particular line (which is much safer than globally disabling this kind of checks).
Upvotes: 0
Reputation: 17622
The cast is present to get rid of compilation error. And its an unchecked way of creating generic array.
Even the ArrayList
follows the same method. You can have a look at this answer to see both checked and unchecked methods
Upvotes: 1
Reputation: 536
T is just a placeholder. You can't instantiate it which is while the compile error exists. At compile time you need to tell the compiler what the placeholder presents. In the case of the code excerpt, the placeholder is anything.
Upvotes: 1