Java cast error trying to create generic array of custom class
This is what I am trying to do:
import java.lang.reflect.*;
class exampleOuter <T extends Number>
{
private exampleInner<T>[] elements;
public exampleOuter(Class<T> type, int size)
{
elements = (exampleInner<T>[]) Array.newInstance(type, size);
}
}
I was told that if I want to create generic arrays of type T, I should use
elements = (T[]) Array.newInstance(type,size);
So, I tried to extend this to my own class, and got a ClassCastException (Ljava.lang.Double; cannot be passed to Lmypackagename.exampleInner; I declare the class basically like this:
exampleOuter<Double> test = new exampleOuter(Double.class,15);
I can declare the inner class just fine, and I can also declare arrays that are not generic to the innerClass, so I imagine something in the constructor of the outer class. Any ideas?
EDIT: I understand what the problem is. When I create a new instance of the array, I create an array of doubles, not exampleInner. I think. If that's correct, I need to find a way to create the exampleInner array while passing only the Double.class to the function.
EDIT 2: I understand that generic arrays are not typical, but I have to use them anyway, because my teacher requires us to use them.
EDIT 3: I was told that in order to use shared arrays I had to allocate them this way and for that I need some thought I guess. The compiler tells me that the class is using unsafe or unchecked operations, but I have to use generic arrays and what I know to do this. If there is a better way, I will change the code.
This is the solution I came across:
public exampleOuter(Class<T> type, int size)
{
innerClass<T> aux = new innerClass<T>();
elements = (exampleInner<T>[]) Array.newInstance(aux.getClass(), size);
}
I thought this would work as well:
elements = (exampleInner<T>[]) Array.newInstance(innerClass<T>.class, size);
But that's not the case, probably because of the way generics are implemented in Java (type erasure and all).
The problem with the first approach is that I am forced to create a new object and instantiate it, despite not really needing it. Also, it makes the code more bloated imo.
EDIT: The second approach didn't work because I used innerClass<T>.class
instead innerClass.class
. Thanks for the suggestion, I will use it now.
You create for a specific T
object of type T[]
and assign it to the field of the type exampleInner<T>[]
that will be the error.
For T extends Number
: the erase type T[]
is Number[]
; for the erasable type exampleInner<T>[]
is exampleInner[]
. But the compiler warnings should have indicated that you were doing something wrong after all.
But you almost certainly don't need to reflect, so don't use it.
source to share
You don't have a "generic array creation" here. The array component type is "exampleInner" (well, it should be exampleInner, but the array component types should be "reified types" so it cannot store at runtime.) Which is known at compile time. Therefore, you don't need to pass the Double.class parameter.
What you really need to do is create an array of the parameterized type. One way to do this is to create an array of raw type and pass it to an array of parameterized type. This will allow you to use the array as usual and get the benefits of generics that you don't need when you get stuff and stuff.
This is technically an untested cast because it could in theory cause unexpected problems later because it can't stop you from putting the wrong type of objects into the array. But since it is a private variable in your class and I am assuming you are only manipulating it in your class and if you trust your own code to use it correctly then it will work.
import java.lang.reflect.*;
class exampleOuter <T extends Number>
{
private exampleInner<T>[] elements;
@SuppressWarnings("unchecked")
public exampleOuter(int size)
{
elements = (exampleInner<T>[]) new exampleInner[size];
}
}
source to share