无法使用通配符编译相关的Java Generics参数

时间:2013-05-17 15:47:21

标签: java generics nested-generics

以下小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 ?>)

如果没有通配符工作,属性模式可以正常工作。

有没有解释为什么编译器不接受通配符输入的值?

2 个答案:

答案 0 :(得分:4)

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

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

ctx.<List<?>, ListAttribute>put(ListAttribute.class, list);
      (T)      (A)

答案 1 :(得分:3)

替换

public <T, A extends Attribute<T>>

public <T, A extends Attribute<? super T>>