Benj Benj - 5 months ago 10
Java Question

java erasures of derived generic type

I'm coming in with a problem I'm getting trying to implement a "two-level" casting.

Below is the simplified code to show what I am trying to do :

public class Array2D<T>
{
private T[][] _array;
....
public T get( int x , int y )
....
public void set( T o , int x , int y )
}


Until there, no problem.

I'm trying to extend this class such as I could encapsulate the use of SoftReferences in the getter and setter :

public class Array2DSoftRefs<T> extends Array2D<SoftReference<T>>
{
public T get( int x , int y )
{
return super.get(x,y).get(); // get the array element, then the SoftReference contents
}
....
public void set( T o , int x , int y )
{
super.set( new SoftReference<T>(o) ,x,y); // generate the SoftReference on-the-fly
}


}

Indeed, I'm kicked off because the compiler / syntax analyzer skips the generics erasures, then the
@Override
annotation cannot help me (captain obvious).

I can't figure out how to return a
T
type from the
SoftReference<T>
template.

I tried to put in two generics
T
and
U
for
SoftReference<T>
, but without succeeding.

Answer

The problem with Array2DSoftRef.get is that you can't override a method and make its return type less specific (e.g. SoftReference<T> -> T).

The problem with Array2DSoftRef.set is that you can't override a method if it has different parameters (e.g. T instead of SoftReference<T>) but you also can't overload it if it will have the same parameters after erasure.

I would recommend you use composition instead of inheritance here:

public class Array2DSoftRefs<T> {

    private final Array2D<SoftReference<T>> inner = ...;

    public T get( int x , int y ) {
        return inner.get(x,y).get();
    }

    public void set( T o , int x , int y ) {
        inner.set(new SoftReference<T>(o), x, y);
    }
}

Otherwise you'll have to rename your get and set in Array2DSoftRefs to avoid the name clash - but remember the parent get and set will still be publicly exposed this way.