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

时间:2012-06-03 10:14:01

标签: java generics

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

感谢。

2 个答案:

答案 0 :(得分:6)

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

您可以使用未经检查的强制转换生成Class<Abc<?>>类型的类对象,并将其移动到实用程序方法或字段。只要Abc s很少,这就非常有效。

@SuppressWarnings("unchecked")
public static Class<Abc<?>> ABC = (Class<Abc<?>>)(Object) Abc.class;

答案 1 :(得分:0)

我发现这个编译..

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;
}

但它只会将同样的问题移到 myFilter()的调用者处。我怀疑Ben Schulz有正确的答案。