Generic array declaration may cause class cast exceptions when extending THashMap

Issue #7 new
Rob Eden created an issue

THashMap declares the _values array as V[] using the type parameter V for the value type. It is initialized with in rehash() and setUp() with (V[]) new Object[]. In the normal case where THashMap is used as THashMap<Foo,Bar> myMap; the _values array is erased to Object[]. But when THashMap is extended as in class TMyHashMap extends THashMap<Foo,Bar> { ... }; TMyHashMap myMap; it will be erased to Bar[]. So in the former case, the compile-time array type is Object[] whereas in the latter case it is Bar[]. At runtime, the array value will be Object[] in both cases. This will cause problems in array assignments in the TMyHashMap subclass because the compiler assumes a Bar[] array and _values[index] = new Bar() fails with java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [com.foo.LBar.

One solution would be declaring _values as Object[] and adding casts to V where needed. This is what java.lang.ArrayList does. Another solution would be to extract the array allocation into a method and allow subclasses to override it:

protected V[] allocate( int size ) {
    return (V[]) new Object[ size ];
}

...

    _values = allocate();

And in TMyHashMap:

@Override
protected Bar[] allocate( int size ) {
    return new Bar[ size ];
}

This might also reduce the number of necessary @SuppressWarnings("unchecked") annotations.

Original SF bug

Comments (0)

  1. Log in to comment