在java中推断Generic方法

时间:2014-07-05 23:51:02

标签: java generics

我有以下场景:我有类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方法。但是这里我们有通配变量clsentitiesCollection

 Class<? extends HasKey<?>> cls and
 Collection<? extends IModel<?>> entitiesCollection 

clzitems具有相似的关系,但我不知道如何将它们传递到doIndex

2 个答案:

答案 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无法再要求ClassIterable相互兼容。 (但是,如果iterable不为空,则该方法可以执行运行时检查以查看其中的对象是否与类参数兼容。)

根本问题是doIndex要求对其参数的参数类型进行约束,因为您没有要完成的信息,因为所有其他类型参数都是问号。

答案 1 :(得分:0)

如果您已经发布了所有来源,我本可以亲自尝试一下。但现在,我只能猜一猜。试试:

public static <T extends IModel<?>> void doIndex(Class<T> clz, Iterable<T> items)
相关问题