It looks like you want to adapt what Josh Bloch calls a Typesafe Heterogenous Container pattern: you are passing a type token Class<T>
, and you want back a List<T>
.
Plain old THC can map a Class<T>
to a T
in a typesafe manner, but since you actually want a List<T>
instead, then you want to use what Neal Gafter calls the super type tokens.
The following snippet is adapted from Crazy Bob Lee's code posted in Neal Gafter's blog:
public abstract class TypeReference<T> {
private final Type type;
protected TypeReference() {
Type superclass = getClass().getGenericSuperclass();
if (superclass instanceof Class<?>) {
throw new RuntimeException("Missing type parameter.");
}
this.type = ((ParameterizedType) superclass).getActualTypeArguments()[0];
}
public Type getType() {
return this.type;
}
}
Now you can create a super type token like these:
TypeReference<String> stringTypeRef =
new TypeReference<String>(){};
TypeReference<Integer> integerTypeRef =
new TypeReference<Integer>(){};
TypeReference<List<Boolean>> listBoolTypeRef =
new TypeReference<List<Boolean>>(){};
Essentially you pass a TypeReference<T>
instead of a Class<T>
. The difference is that there is no List<String>.class
, but you can make a TypeReference<List<String>>
.
So now we can make our container as follows (the following is adapted from Josh Bloch's original code):
public class Favorites {
private Map<Type, Object> favorites =
new HashMap<Type, Object>();
public <T> void setFavorite(TypeReference<T> ref, T thing) {
favorites.put(ref.getType(), thing);
}
public <T> T getFavorite(TypeReference<T> ref) {
@SuppressWarnings("unchecked")
T ret = (T) favorites.get(ref.getType());
return ret;
}
}
Now we can put the two together:
Favorites f = new Favorites();
f.setFavorite(stringTypeRef, "Java");
f.setFavorite(integerTypeRef, 42);
f.setFavorite(listBoolTypeRef, Arrays.asList(true, true));
String s = f.getFavorite(stringTypeRef);
int i = f.getFavorite(integerTypeRef);
List<Boolean> list = f.getFavorite(listBoolTypeRef);
System.out.println(s); // "Java"
System.out.println(i); // "42"
System.out.println(list); // "[true, true]"
Neal Gafter argued in his blog that with some more bells and whistles, TypeReference
for super type tokens will make a worthy inclusion in the JDK.
Attachments
References