Search code examples
javagenericsderived-classtype-erasureoverriding

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.


Solution

  • 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.