Jason S Jason S - 6 days ago 6
Java Question

java: converting from List<SomeClass> to List<SomeInterface> when SomeClass implements SomeInterface

I'm having a brain cramp: I have a

public interface SomeInterface
and a
static private class SomeClass
and am trying to return a
List<SomeInterface>
from one of my methods, but I get the error (on the
return list;
line below):

Type mismatch: cannot convert from List<GenericList1.SomeClass> to
List<GenericList1.SomeInterface>


How can I fix this without having to create a new list?

Clarification: I do not want the list to be created as
List<SomeInterface>
(perhaps the obvious solution) because privately I want to maintain a
List<SomeClass>
to allow future access to SomeClass's methods beyond the ones in the public interface. This isn't shown in the example case below, but in my real program I need this.

import java.util.ArrayList;
import java.util.List;

public class GenericList1 {

public interface SomeInterface
{
public int getX();
}

private static class SomeClass implements SomeInterface
{
final private int x;
@Override public int getX() {
return this.x;
}
public SomeClass(int x) { this.x = x; }
}

public static void main(String[] args) {
List<SomeInterface> list = createList(10);
printList(list);
}

private static void printList(List<SomeInterface> list) {
for (SomeInterface si : list)
System.out.println(si.getX());
}

private static List<SomeInterface> createList(int n) {
List<SomeClass> list = new ArrayList<SomeClass>();
for (int i = 0; i < n; ++i)
list.add(new SomeClass(i));
return list;
}
}

Answer

You should redefine your method as

private static List<? extends SomeInterface> createList(int n) { ...

and similarly, the other list declarations. This allows you to deal with generic lists polymorphically, as long as you only read values from them.

(Should you want to add new elements to a list, you should use List<? super SomeInterface> instead.)

This idiom is known by the abbreviation PECS - Producer: Extends / Consumer: Super, coined by Josh Bloch in Effective Java 2nd Edition, Item 28.

As others have noted, this idiom is needed because a List<SomeClass> is not a List<SomeInterface>, even when SomeClass implements SomeInterface. The reason for this is thoroughly explained in the referred document.