7

由于不清楚的原因,以下 Java 小示例无法编译:

package genericsissue;

import java.util.ArrayList;
import java.util.List;

interface Attribute<V> {}

interface ListAttribute extends Attribute<List<?>> {}

public class Context {
    public <T, A extends Attribute<T>> void put(Class<A> attribute, T value) {
        // implementation does not matter for the issue
    }

    public static void main(String[] args) {
        Context ctx = new Context();
        List<?> list = new ArrayList<String>();
        ctx.put(ListAttribute.class, list);
    }
}

带有 ctx.put 的行会产生以下错误:

Context.java:18: <T,A>put(java.lang.Class<A>,T) in genericsissue.Context cannot be applied to (java.lang.Class<genericsissue.ListAttribute>,java.util.List<capture#35 of ?>)

如果不使用通配符,则属性模式可以正常工作。

有什么解释为什么编译器不接受通配符类型的值?

4

2 回答 2

4

问题是,参数类型list不是真的List<?>。编译器首先进行“通配符捕获”以将其类型转换为List<x> for some x. 通常这会提供更多信息和帮助。但不是你的情况。它促使类型推断认为T=List<x>,但ListAttribute不扩展Attribute<List<x>>

您可以提供显式类型参数来解决它

ctx.<List<?>, ListAttribute>put(ListAttribute.class, list);
      (T)      (A)
于 2013-05-17T16:02:44.670 回答
3

代替

public <T, A extends Attribute<T>>

public <T, A extends Attribute<? super T>>
于 2013-05-17T15:54:59.717 回答