让我们假设以下方法(比如来自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)
谢谢.
这个问题没有令人满意的答案.使用无界通配符参数化的类型的类文字只能在理论上解决,我们只是没有它们.
您可以Class<Abc<?>>使用未经检查的强制转换生成-typed类对象,并将其移动到实用程序方法或字段.只要有很少的Abcs,这很好用.
@SuppressWarnings("unchecked")
public static Class<Abc<?>> ABC = (Class<Abc<?>>)(Object) Abc.class;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1116 次 |
| 最近记录: |