将带有类型参数的类传递给函数

Jir*_*rka 5 java generics

让我们假设以下方法(比如来自Guava的Iterables):

public static <T> Iterable<T> filter(final Iterable<?> unfiltered, final Class<T> type) {
    return null;
}
Run Code Online (Sandbox Code Playgroud)

而这个集合:

Set<?> objs = ...;
Run Code Online (Sandbox Code Playgroud)

然后编译以下代码并正确派生泛型

Iterable<String> a2 = Iterables.filter(objs, String.class);
Run Code Online (Sandbox Code Playgroud)

(在Guava中,这将返回所有字符串的迭代objs.)

但现在让我们假设以下类:

static class Abc<E> {
    E someField;
}
Run Code Online (Sandbox Code Playgroud)

我不知道怎么打电话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
Run Code Online (Sandbox Code Playgroud)

只有a3编译,但是我在Abc上没有参数,因此在后续代码中没有进行泛型类型检查.

我知道类型参数在运行时不存在,所以我不想尝试编写如下代码:

Iterable<Abc<String>> a9 = Iterables.filter(objs, Abc<String>.class); // Compile error
Run Code Online (Sandbox Code Playgroud)

我只想过滤Abc类型的所有对象(如a3所做),但在结果中包含泛型参数.我发现这样做的唯一方法是以下,这是愚蠢的:

Iterable<Abc<?>> a10 = new HashSet<Abc<?>>();
for (Abc<?> a : Iterables.filter(objs, Abc.class)) {
    ((Set<Abc<?>>)a10).add(a);
}
Run Code Online (Sandbox Code Playgroud)

谢谢.

Ben*_*ulz 6

这个问题没有令人满意的答案.使用无界通配符参数化的类型的类文字只能在理论上解决,我们只是没有它们.

您可以Class<Abc<?>>使用未经检查的强制转换生成-typed类对象,并将其移动到实用程序方法或字段.只要有很少的Abcs,这很好用.

@SuppressWarnings("unchecked")
public static Class<Abc<?>> ABC = (Class<Abc<?>>)(Object) Abc.class;
Run Code Online (Sandbox Code Playgroud)