【问题标题】:Inferring Generic method in java在java中推断通用方法
【发布时间】:2014-07-07 04:20:53
【问题描述】:

我有以下情况,我有类 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) 

其中参数 clz 和基于相同类型 T 的项目。如果我们只有一个参数,可以使用wildcard capture 方法。但是这里我们有通配符变量clsentitiesCollection

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

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

【问题讨论】:

  • 你的编译错误是什么?
  • 这是我什至无法编译的问题。错误:) java: 类 A 中的方法 doIndexFor 不能应用于给定类型;必需:java.lang.Class,java.lang.Iterable 找到:java.lang.Class>,java.util.Collection> 原因:不存在类型变量 T 的实例,因此参数类型 java.util.Collection> 符合形参类型 java.lang.Iterable

标签: java generics


【解决方案1】:

Foo&lt;? extends IModel&lt;?&gt;&gt; 不能被视为Foo&lt;T extends IModel&lt;T&gt;&gt;。这是不一样的。两个?s 中的每一个都是独立的,可能指代不同的未知事物,但两个Ts 都指代相同的未知事物。

如果doIndex 有两个类型参数TC,格式为:&lt;T,C extends IModel&lt;T&gt;&gt;,您可以使用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?s 不一定与 entitiesCollection?s 相同。

不知道有没有好的解决办法。如果您在调用方法上也使用 &lt;T extends IModel&lt;T&gt;&gt; 之类的类型参数,然后在整个代码中使用 T 而不是问号,您也许可以调用 doIndex

如果确实无法做到(有时是这种情况),并且您必须在任何地方使用问号,那么在我看来,类型参数没有用处,应该删除或绕过。您可能知道这一点,但即使使用原始方法声明,删除泛型的不安全强制转换也能完成工作:

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 相互兼容。 (但是,如果可迭代对象不为空,则该方法可以进行运行时检查以查看其中的对象是否与类参数兼容。)

根本问题是doIndex 要求对其参数的参数类型进行限制,而您没有要满足的信息,因为您的所有其他类型参数都是问号。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      • 2012-03-14
      • 1970-01-01
      • 2020-03-06
      相关资源
      最近更新 更多