Search code examples
javagenericsparameterizedgeneric-type-argument

Shortcut for parameterized type?


I'm working with code where I need to generate a lot of List<Map<String,Object>> and it's unwieldy to have to type e.g. bob = new List<Map<String,Object>> all the time.

I tried to create an empty class a la

class ListMap extends List<Map<String,Object>> {}

but then methods that take List<Map<String,Object>> don't accept a new ListMap() as their type, and I get errors from methods that return List<Map<String,Object>> if I assign them to a ListMap. Basically I want Java to treat my ListMap as the same as a List> ... because it is, at least via inheritance, in theory.


Solution

  • Since you have methods returning List<Map<String,Object>>, but want to assign that to a variable of type ListMap, and the List<Map<String,Object>> might be implemented as an ArrayList<Map<String,Object>>, you cannot make it directly assignment-compatible with a ListMap.

    So, you need to wrapper the returned object with a delegating proxy. First, create a generic delegating class for List. They are easy to create, e.g. Eclipse can create all the delegating methods for you by selecting "Generate Delegate Methods..." from the "Source" pull-down menu.

    It should look like this:

    public class DelegatingList<E> implements List<E> {
        private final List<E> list;
        protected DelegatingList(List<E> list) {
            this.list = list;
        }
        @Override
        public int size() {
            return this.list.size();
        }
        @Override
        public boolean isEmpty() {
            return this.list.isEmpty();
        }
        @Override
        public boolean contains(Object o) {
            return this.list.contains(o);
        }
        // many other delegating methods from List
    }
    

    Now define your ListMap interface:

    public interface ListMap extends List<Map<String,Object>> {
        public static ListMap newArrayList() {
            return wrap(new ArrayList<>());
        }
        public static ListMap wrap(List<Map<String,Object>> list) {
            if (list instanceof ListMap)
                return (ListMap) list;
            class Wrapper extends DelegatingList<Map<String,Object>> implements ListMap {
                protected Wrapper() {
                    super(list);
                }
            }
            return new Wrapper();
        }
    }
    

    It is now simple to use:

    ListMap myListMap = ListMap.newArrayList();
    methodAcceptingListOfMapOfStringToObject(myListMap);
    
    ListMap x = ListMap.wrap(methodReturningListOfMapOfStringToObject());