[英]unchecked warning on Class<Collection>
假设我具有以下方法,该方法可用于创建指定的给定类型的集合。
private static Collection<?> void create(Class<? extends Collection<?>> cls) {
return cls.newInstance();
}
如果在运行时传递cls参数,那么这一切都很好:
List<String> list = new LinkedList<String>();
create(list.getClass());
但是,如何在没有未经检查的警告的情况下在代码中调用此方法? 假设我想执行以下操作:
create(LinkedList.class);
它将抱怨未定义create(Class),严格来说,这是正确的,因为List不是#capture的Collection,但是我如何使它工作?
非常感谢!
尼尔·古夫特(Neal Gafter) 在这里几乎完全讨论了这个问题。 解决方法是使用超级类型令牌 。 我相信,Guice就是用来维护通用类型信息的。
基本上,这是一个额外的类,可以用来表示一个类型,而不是使用Foo.class
。 您可以这样使用它:
TypeReference<LinkedList<String>> x = new TypeReference<LinkedList<String>>() {};
create(x);
请注意,您尝试使用原始类型LinkedList
仍然会导致编译器抱怨,这是故意的-使用原始类型时,您基本上选择了类型安全。 但是,此方案允许您以其他方式难以表达的泛型类型。
我们这里有两种通用类型,一种是集合的子类型,一种是集合的元素类型。 以下代码可以工作:
private static <C extends Collection<E>, E>
C create(Class<C> cls) throws Exception
{
return cls.newInstance();
}
使用示例。 没有警告。
Class<LinkedList<String>> clazz = ...;
LinkedList<String> result = create(clazz);
现在的问题变成我们如何获得clazz
? 您必须非常说服编译器:
List<String> list = new LinkedList<String>();
clazz = (Class<LinkedList<String>>)list.getClass();
clazz = (Class<LinkedList<String>>)(Class<?>)LinkedList.class;
我们可以使用一种实用方法来简化类型转换:
public static <C extends Collection, E, T extends Collection<E>>
Class<T> type(Class<C> classC, Class<E> classE)
{
return (Class<T>)classC;
}
//usage:
clazz = type(LinkedList.class, String.class);
result = create(clazz);
有趣的是递归的:
Class<LinkedList<LinkedList<String>>> clazz2;
LinkedList<LinkedList<String>> result2;
clazz2 = type(LinkedList.class, clazz);
result2 = create(clazz2);
但是在某个时候,我们必须停止这场愚蠢的比赛。 泛型打字应该帮助我们,而不是折磨我们。 当它变得太麻烦并且使我们的程序无法阅读时,请将其删除。 使用我们幸福生活多年的该死的原始类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.