I just implement a MapBuilder to build map easy,
But when i try to get an instance of HashMap.class,I suddenly found that I can’t use HashMap.class to get such an instance.
It’s illegal!
So can anybody tell me why and how to solve this problem?
The MapBuilder is follow:
import java.util.Map;
public abstract class MapBuilder {
public static <K, V, T extends Map<K, V>> InnerMapBuilder<T, K, V> start(
Class<T> clazz) {
return new InnerMapBuilder<>(clazz);
}
public static class InnerMapBuilder<T extends Map<K, V>, K, V> {
private T target;
public InnerMapBuilder(Class<T> clazz) {
try {
target = clazz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public InnerMapBuilder<T, K, V> put(K key, V val) {
target.put(key, val);
return this;
}
public T get() {
return target;
}
}
}
And the test code is below:
public static void main(String[] args) {
HashMap<String, String> v = start(HashMap<String,String>.class).put("a", "b").get();
System.out.println(v);
}
It’s impossible to obtain a parameterized class type variable for a generic type, as Reimeus has said. So you have three choices.
First, you can live with the unchecked cast:
Second, you can reify the parameters for a class by extending it (in this example, using an anonymous inner class):
Or third, and best, just take the
Mapinstance instead of a class instart(). You’re not saving the user any work by taking theClassrather than an instance ofMap, and the first thing you do is create an instance of it.By passing it in, the user can even tweak the settings of the map (e.g. for a
HashMap, set the load factor, forTreeMap, specify theComparator) so it’s a better alternative anyway. If you need to, you can assert that it’s empty when it’s passed in.If for some reason you really need a factory, don’t use
Class: it doesn’t work well as a factory, because the only way you can customize the instance thatClasscreates is by subclassing the class and providing a new no-arg constructor. Just create an interfaceFactory<T>that has a methodT create()and then accept aFactory<? extends Map<K, V>.