In my readList method readList I would like to build a user type java.util.List (a specific list type is a parameter). However, I do not want to restrict readList to ArrayList or LinkedList ; the user can provide his own implementation of java.util.List . The method can also cache the list, if possible, so the method should return a list. I have tried several things. Which of the following options is the βbestβ API in your view, or is there another, even better?
The following compilations, but I get a compiler warning: "Security type: an expression of type ArrayList requires an raw conversion to match an ArrayList," so this is not a good solution:
void classParameter() { ArrayList<String> a = readList(ArrayList.class); LinkedList<String> b = readList(LinkedList.class); } <X, T extends List<X>> T readList(Class<T> clazz) { try { return clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } }
The following compilation, but I still get a warning about the compiler, and also does not work as expected:
void classTypeParameters() { ArrayList<String> a = readList(ArrayList.class, String.class); LinkedList<String> b = readList(LinkedList.class, Integer.class); } <T extends List<X>, X> T readList(Class<T> clazz, Class<X> type) { try { return clazz.newInstance(); } catch (Exception e) { throw new RuntimeException(e); } }
The following works, and my personal favorite. It checks the type of list. Which is a bit dangerous, someone mistakenly forgot to assign a result. This could be solved by renaming readList to readListWithTemplate or so, it would be more obvious that you need to use the return value. It is similar to List.toArray(T[] a) :
void template() { ArrayList<String> a = readList(new ArrayList<String>()); LinkedList<String> b = readList(new LinkedList<String>()); // wrong usage: List<String> c = new LinkedList<String>(); readList(c); } @SuppressWarnings("unchecked") <X, T extends List<X>> T readList(T template) { try { return (T) template.getClass().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } }
The "super marker type" also works, but it can be a little difficult to understand for developers who are not familiar with this template, and in Eclipse I get a warning: "An empty block must be documented", which I would like to avoid:
void superTypeToken() { ArrayList<String> a = readList(new ListType<ArrayList<String>>() {}); LinkedList<String> b = readList(new ListType<LinkedList<String>>() {}); } abstract static class ListType<X extends List<?>> {
Which one do you prefer? Or is there a better solution?