How do I convert from List<?> to List<T> in Java using generics?

Viewed 18736

In Java, how do I convert List<?> to List<T> using a general purpose method so that I can replace patterns like the following with a single method call:

List untypedList = new ArrayList();  // or returned from a legacy method
List<Integer> typedList = new ArrayList<Integer>();
for (Object item: untypedList)
    typedList.add((Integer)item);

Note that the above code does not generate any type-safety warnings and, ideally, your solution shouldn't generate any such warnings, either.

Will the following solution work provided that list Class<L> has a public default constructor?

public class ListUtil {
    public static <T, L extends List<T>> L typedList(List<?> untypedList, Class<T> itemClass, Class<L> listClass) {
        L list = null;
        try {
            list = listClass.newInstance();
        } catch (InstantiationException e) {
        } catch (IllegalAccessException e) {
        }
        for (Object item: untypedList)
            list.add(itemClass.cast(item));
        return list;
    }
}

(Note that listClass.newInstance() throws InstantiationException or IllegalAccessException if an instance of Class<L> does not have a public default constructor. What problems may arise if the method does not properly handle these exceptions?)

Notes:

  • T is the type of each item in the resulting list.
  • L is the type of the list that I wish to create (which extends List<T>).
  • untypedList is the "untyped" input list, effectively the same as List<Object>.
  • itemClass represents the runtime class of T.
  • listClass represents the runtime class of L.
9 Answers
Related