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.

0


source to share


4 answers


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.

+1


source


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.

0


source


T expands the number and you are trying to pass it to exampleInner, which I doubt is in the correct place in the Number hierarchy.

Try this without your example Inner. Or try passing exampleInner as the type argument to exampleOuter's constructor.

0


source


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];
    }
}

      

0


source







All Articles