Hi! Well, I'm having an issue with a generic array for a class I implemented.
I wanted to implement a vector that held generic types. Its just a very thing wrapper around an array to work as a base for a matrix class.
I did the following:
public class CmpVector<Type>
{
public final Type[] array;
@SuppressWarnings("unchecked")
public CmpVector ( final int size )
{
this.array = (Type[]) new Object[size];
}
public Type getValueAt ( final int index )
{
return this.array[index];
}
public void setValueAt ( final int index, final Type val )
{
this.array[index] = val;
}
}
(i'm omiting other irrelevant methods/constructors)
I noticed that the stock JDK "ArrayList" implementation used instead an Object[] for storing the values, doing casts to "T" back and forth in all accessor and mutator methods. That's probably because you can't instantiate a new generic array in Java due type erasure (ie, new Type[size] gives a compiler error), but I can declare a generic array reference.
So I thought, instead of creating an array of Object, I could declare an array of Type, give it a new array of Object, and as long as I store Type objects in it, I shouldn't have issues. Besides, it would work with my original idea of having the array public, since if I made an Object[] array instead, it would need to be private so you just can't assign any object to it.
Now enter the static generic method for filling arrays:
public static <Type> void arrayFill ( final Type[] array, final Type value )
{
if ( array.length > 0 )
{
array[0] = value;
}
for ( int i = 1; i < array.length; i += i )
{
System.arraycopy( array, 0, array, i, ( ( array.length - i ) < i ) ? ( array.length - i ) : i );
}
}
This method works with arrays directly, thus no Vector<Type> interface.
It was all good and well until I made the following call:
arrayFill(particleVec.array, null);
I'm sending the Vector<ParticleTag>'s array and a null to the method, so it fills the array with null values. I get a "ClassCastException" saying that I can't cast an Object to a ParticleTag. ParticleTag is an interface that RidgeParticle and RiverParticle implement (yes, its from my terrain generator ).
The thing that I don't understand is that setValueAt(index, particle) method works fine. If I do a getValueAt(index) I get the ParticleTag just fine too. But when I operate with the array directly, ClassCastException.
I have another method that receives a specific type of array (so no generics there), and I can't pass it the array of Vector<Type> either. I made an arrayFill as method of the Vector<Type> classe and it works fine that way.
I don't understand what's so special about the object itself that working on the array inside Vector through its methods works fine, but working with the array outside of the object doesn't. In my mind either it would work fine on both cases or it wouldn't work at all. At worst it should make a downcast from Object to ParticleTag, but that should be fine since they do are ParticleTags.
Any ideas?
EDIT: I definitively can't access the array at all, for example, doing a simple:
System.out.println ( new CmpVector<ParticleTag>(100).array.length);
throws a ClassCastException.
While doing it like this:
System.out.println ( new CmpVector<ElevationState>(100).getLength() );
prints 100 as expected (and the getLength() implementation is just a return array.length)