我有以下场景:我有类Class<? extends IModel<?>> aCls
和集合Collection<? extends IModel<?>> entitiesCollection
并尝试将它们传递给方法<T extends IModel<T>> void doIndex(Class<T> clz, Iterable<T> items)
,但不断获得编译时异常。我试过通配符捕获和其他方式,但没有运气。我一定错过了一些明显的东西。将不胜感激。
Multimap<Class<? extends IModel<?>>, IModel<?>> entityMultimap = ArrayListMultimap.create();
for (IModel<?> entity : models) {
Class<? extends IModel<?>> aCls = entity.getClass();
entityMultimap.put(aCls, entity);
}
for (Class<? extends HasKey<?>> cls : entityMultimap.keySet()) {
Collection<? extends IModel<?>> entitiesCollection = entityMultimap.get(cls);
doIndex(cls, entitiesCollection);
}
public static <T extends IModel<T>> void doIndex(Class<T> clz, Iterable<T> items) {
.....
}
更新:有人将此标记为其他通用通配符相关问题的副本。然而,这是非常不同的情况。我们拥有的是
public static <T extends IModel<T>> void doIndex(Class<T> clz, Iterable<T> items)
其中params clz和基于相同类型T的项目。如果我们只有一个参数,可以使用wildcard capture方法。但是这里我们有通配变量cls
和entitiesCollection
:
Class<? extends HasKey<?>> cls and
Collection<? extends IModel<?>> entitiesCollection
与clz
和items
具有相似的关系,但我不知道如何将它们传递到doIndex
。
答案 0 :(得分:2)
Foo<? extends IModel<?>>
无法被视为Foo<T extends IModel<T>>
。它不一样。这两个?
中的每一个都是独立的,可能会引用不同的未知内容,但T
都指的是同一个未知的内容。
如果doIndex
在表单T
中有两个类型参数C
和<T,C extends IModel<T>>
,则可以使用Class
参数调用它或者Iterable
参数,但仍然不能同时进行。所以这会编译:
static <T,C extends IModel<T>> void doIndex(Class<C> clz, Iterable<C> items) {}
static {
Class<? extends IModel<?>> cls = null;
Collection<? extends IModel<?>> entitiesCollection = null;
doIndex(cls, null);
doIndex(null, entitiesCollection);
}
但是这个额外的行不会编译:
doIndex(cls, entitiesCollection);
为什么呢?与以前一样的问题:cls
&#39; ?
与entitiesCollection
?
s不一定是同一个未知事物。
我不知道是否有一个好的解决方案。如果您在调用方法上使用doIndex
等类型参数,则可以调用<T extends IModel<T>>
,然后在代码中使用T
而不是问号。
如果真的无法完成(有时候这种情况),并且你必须在任何地方使用问号,我觉得类型参数没有用,应该删除或绕过。您可能知道这一点,但即使使用原始方法声明,删除泛型的不安全强制转换也可以完成工作:
static <T extends IModel<T>> void doIndex(Class<T> clz, Iterable<T> items) {}
static {
Class<? extends IModel<?>> cls = null;
Collection<? extends IModel<?>> entitiesCollection = null;
doIndex((Class)cls, (Collection)entitiesCollection); // has a warning, but compiles
}
或者,可以放宽对doIndex
的约束。 doIndex
的此声明使其无需警告即可生效,因为如果类型相同,它不再关注:
static void doIndex(Class<? extends IModel<?>> clz, Iterable<? extends IModel<?>> items) {}
优点也是缺点:doIndex
无法再要求Class
和Iterable
相互兼容。 (但是,如果iterable不为空,则该方法可以执行运行时检查以查看其中的对象是否与类参数兼容。)
根本问题是doIndex
要求对其参数的参数类型进行约束,因为您没有要完成的信息,因为所有其他类型参数都是问号。
答案 1 :(得分:0)
如果您已经发布了所有来源,我本可以亲自尝试一下。但现在,我只能猜一猜。试试:
public static <T extends IModel<?>> void doIndex(Class<T> clz, Iterable<T> items)