您似乎想要适应 Josh Bloch 所说的 Typesafe Heterogenous Container 模式:您正在传递一个类型标记 Class<T>,并且您想要返回一个 List<T>。
普通的旧 THC 可以以类型安全的方式将 Class<T> 映射到 T,但由于您实际上想要一个 List<T>,所以您想使用 Neal Gafter 所称的 超级类型令牌。
以下 sn-p 改编自 Neal Gafter 博客中发布的 Crazy Bob Lee 的代码:
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); // "Java"
System.out.println(i); // "42"
System.out.println(list); // "[true, true]"
Neal Gafter 在他的博客中指出,如果有更多的花里胡哨,TypeReference 用于超级类型令牌将值得包含在 JDK 中。
附件
参考文献