让我们假设以下方法(比如来自 Guava 的 Iterables):
public static <T> Iterable<T> filter(final Iterable<?> unfiltered, final Class<T> type) {
return null;
}
和这个集合:
Set<?> objs = ...;
然后编译以下代码并正确派生泛型
Iterable<String> a2 = Iterables.filter(objs, String.class);
(在 Guava 中,这将返回所有字符串的迭代objs
。)
但现在让我们假设以下类:
static class Abc<E> {
E someField;
}
我不知道如何调用filter
和获取Iterable<Abc<?>>
:
Iterable<Abc> a3 = Iterables.filter(objs, Abc.class);
Iterable<Abc<?>> a4 = Iterables.filter(objs, Abc.class); // Compile error - Abc and Abc<?> are incompatible types
Iterable<Abc<?>> a5 = Iterables.filter(objs, Abc<?>.class); // Compile error
Iterable<Abc<?>> a6 = Iterables.<Abc<?>>filter(objs, Abc.class); // Compile error
Iterable<Abc<?>> a7 = (Iterable<Abc<?>>) Iterables.filter(objs, Abc.class); // Compile error - inconvertible types
Iterable<Abc<?>> a8 = Iterables.filter(objs, new Abc<?>().getClass()); // Compile error
Iterable<Abc<?>> a8a = Iterables.filter(objs, new Abc<Object>().getClass()); // Compile error
只有 a3 可以编译,但是我没有 Abc 上的参数,因此在后续代码中没有进行泛型类型检查。
我知道类型参数在运行时不存在,所以我不会尝试编写如下代码:
Iterable<Abc<String>> a9 = Iterables.filter(objs, Abc<String>.class); // Compile error
我只想过滤所有 Abc 类型的对象(就像 a3 一样),但在结果中有泛型参数。我发现这样做的唯一方法是以下,这很愚蠢:
Iterable<Abc<?>> a10 = new HashSet<Abc<?>>();
for (Abc<?> a : Iterables.filter(objs, Abc.class)) {
((Set<Abc<?>>)a10).add(a);
}
Thanks.