我尝试编写一个方法,该方法将使用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
导致此警告的原因,我该如何解决?据我所知,一切都很安全。该方法本身的实现不是问题。这并没有引发任何警告。只有它的调用是问题。
答案 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);