Restrict a generic Class parameter to classes that implement Map

Use a Supplier instead of a Class:

public MapBuilder(Supplier<? extends Map<K, V>> supplier) {
    map = supplier.get();
}

Which then can be called like this:

MapBuilder<Integer, Integer> builder = new MapBuilder<>(LinkedHashMap::new);

This is also safer, because a Class<Map> could have no default constructor, which would throw an error (which is not very responsive code)


The following will work:

public MapBuilder(Class<? extends Map> mapType) throws Exception {
    map = mapType.newInstance();
}

The problem is that LinkedHashMap.class is

Class<LinkedHashMap>

and not something like

Class<LinkedHashMap<Integer, String>>

These are also inconvertible types (so you can't cast it) and there's no way to get an instance of the latter.

What you can do is change the constructor to

public MapBuilder(Class<? extends Map> mapType) throws Exception

Generics are erased at run-time so at run-time all Maps will behave just like Map<Object, Object> anyway. Therefore it doesn't matter that the class you're constructing from is using the raw type.


By the way, Class::newInstance is deprecated. Use

mapType.getConstructor().newInstance()

Tags:

Java

Generics