看起来你想采用Josh Bloch所称的类型安全异构容器模式:你正在传递一个类型令牌Class<T>
,并希望得到一个List<T>
。
普通的THC可以以类型安全的方式将Class<T>
映射到T
,但由于你实际上想要一个List<T>
,所以你需要使用Neal Gafter所称的超级类型令牌。
下面的片段改编自Crazy Bob Lee在Neal Gafter的博客中发布的代码:
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;
}
}
现在您可以创建像这样的
超类型令牌:
TypeReference<String> stringTypeRef =
new TypeReference<String>();
TypeReference<Integer> integerTypeRef =
new TypeReference<Integer>();
TypeReference<List<Boolean>> listBoolTypeRef =
new TypeReference<List<Boolean>>();
基本上,你需要传递一个
TypeReference<T>
而不是一个
Class<T>
。区别在于没有
List<String>.class
,但是你可以创建一个
TypeReference<List<String>>
。
因此,现在我们可以按照以下方式创建容器(以下内容改编自Josh Bloch的原始代码):
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;
}
}
现在我们可以将两者结合起来:
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);
System.out.println(i);
System.out.println(list);
Neal Gafter在他的博客中提出,通过一些额外的功能,
TypeReference
可以成为JDK中值得包含的超类型标记。
附件
参考资料
List<Fruit>
而不是LinkedList<Fruit>
。 - polygenelubricants