Alex Rivera | Logout

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

Asked 2010-08-23T14:55:43.257
16

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.
Edit
Report

2 Answers

1

The Class.newInstance() method throws two checked exceptions IllegalAccessException and InstantiationException. These have to be either caught or declared in the method signature for your method.

For the record, these exceptions are thrown in a variety of situations; e.g.

  • the class defines no no-args constructor
  • the constructor is not visible
  • the class is abstract or an interface
  • the class object denotes an array type, primitive type or the void "type".

This is actually unrelated to the fact that the method is generic, and the associated typing issues.

answered 2010-08-23T15:28:08.340
0

I don't believe what you are trying to do is possible. This is because of Generics work:

At compile time all ingoing types of a typed list are checked and all outgoing objects are casted to the type of the list - and from that moment we are talking about an untyped "list". Generics are just syntactic sugar, unfortunately.

answered 2010-08-23T15:03:09.140

Your Answer