[2007-01-11] Generics in Java and Return Types

Consider a class C that implements an interface I.

While the following is allowed:


I foo( )
{
return new C( );
}

the following is not:

ArrayList<I> foo( )
{
return new ArrayList<C>( );
}

In the first case, callers expect to get an object implementing the interface I and therefore it is correct for foo( ) to return an object of class C. In the second case, callers expect to get an ArrayList containing objects implementing the interface I and therefore it should again be correct for foo( ) to return an ArrayList containing objects of class C, right?

Consider what happens if the compiler were to allow such code to compile. Callers can then add objects of another class X, which also implements the interface I, to the returned ArrayList with the result that the original ArrayList, which is only supposed to contain objects of class C, now also contains objects of an incompatible class X!

A better way to define the second case is:


ArrayList<? extends I> foo( )
{
return new ArrayList<C>( );
}

(You can also return an ArrayList<I> instead, but that loosens up the definition of the returned object.)

Thanks to Steve Onorato for clearing up my muddied thinking.

(Originally posted on Blogspot.)

Other Posts from 2007