5

让我们假设以下方法(比如来自 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.

4

2 回答 2

6

There is no satisfactory answer to this question. Class literals for types parameterized with unbounded wildcards only would work out in theory, we just don't have them.

You can produce the Class<Abc<?>>-typed class object with an unchecked cast and move it to a utility method or field. As long as there are few Abcs, this works quite nicely.

@SuppressWarnings("unchecked")
public static Class<Abc<?>> ABC = (Class<Abc<?>>)(Object) Abc.class;
于 2012-06-03T12:04:21.427 回答
0

I found this compiles..

public static <T> Iterable<Abc<T>> myFilter (Iterable<Abc<T>> myIterator) {
    Class<Abc<T>> myClass = null;
    Iterable<Abc<T>> a3 = Iterables.filter(myIterator, myClass); 
    return a3;
}

But it just moves the same problem up to the caller of myFilter(). I suspect Ben Schulz has the correct answer.

于 2012-06-03T11:40:00.797 回答