将集合过滤为指定类型会生成编译器警告

时间:2014-03-17 20:32:01

标签: java generics collections

我尝试编写一个方法,该方法将使用Collection<?>并删除所有非{1}类型的对象,返回原始集合或新集合,如下所示方法签名:

T

例如,我有一个public static <T,C extends Collection<T>> C objectsOfType(Collection<?> in, Class<T> type, Class<C> collectionType); ,其中包含字符串和其他一些对象。我想要一个Collection<?>

List<String>

最终一切顺利。 Collection<?> allObjects = getAllObjects(); List<String> stringObjects = objectsOfType(allObjects, String.class, ArrayList.class); 如果objectsOfType仅包含allObjects,则会返回ArrayList,否则会创建新的Strings,并使用ArrayList<String>填充String allObjects的元素。我需要添加另一个参数以允许返回任何List,因为ArrayList比返回值所需的更具体,因为该类必须具有构造函数。但那不是问题。

问题是调用objectsOfType的编译器警告,我无法弄清楚原因:

  

类型安全:未经检查的调用   objectsOfType(Collection&lt; capture#1-of?&gt;,Class&lt; String&gt ;, Class&lt; ArrayList&gt;)   泛型方法objectsOfType(Collection&lt;?&gt ;,Class&lt; T&gt;,Class&lt; C&gt;)   类型CollectionUtilities

导致此警告的原因,我该如何解决?据我所知,一切都很安全。该方法本身的实现不是问题。这并没有引发任何警告。只有它的调用是问题。

1 个答案:

答案 0 :(得分:1)

ArrayList.class不能分配给Class<C>,即{/ 1}}在严格/已检查的上下文中,因此传递此参数需要未经检查的分配,因此需要警告。 Class<List<String>>的类型只是ArrayList.class,其中Class<ArrayList>是原始类型。无法使用ArrayList运算符指定类.class

你真的需要签名中的ArrayList<String>参数吗?如果用工厂回调替换它(例如Java 8的Class<C>)会怎么样?

或者,只需返回Supplier<C>(并在所有情况下使用相同的List<T>实现),在此过程中简化您的签名:

List

您也可以删除通配符,让编译器推断源项类型:

public static <T> List<T> objectsOfType(Collection<?> in, Class<T> type);

但请注意,对于输入集合类型(您可能已经预期),上述两者都是松散的。如果您想要严格,可以将输入项类型限制为结果类型的超类:

public static <T, R> List<R> objectsOfType(Collection<T> in, Class<R> type);