无法使用通配符编译相关的Java泛型参数
以下小Java示例无法编译,原因不清楚:无法使用通配符编译相关的Java泛型参数,java,generics,nested-generics,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 At
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);
}
}
包一般性问题;
导入java.util.ArrayList;
导入java.util.List;
接口属性{}
接口ListAttribute扩展属性列表=新建ArrayList();
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 ?>)
Context.java:18:put(java.lang.Class,T)在genericsissue中。上下文不能应用于(java.lang.Class,java.util.List)
如果不使用通配符,则属性模式可以正常工作
有没有解释为什么编译器不接受通配符类型的值?Replace
public <T, A extends Attribute<T>>
公共
与
public问题是,list
的参数类型实际上不是list
。编译器首先执行“通配符捕获”,将其类型转换为某些x的列表。通常,这会提供更多信息和帮助。但对你来说不是。它促使类型推断认为T=List
,但listtribute
不扩展属性
您可以提供显式类型参数来解决此问题
ctx.<List<?>, ListAttribute>put(ListAttribute.class, list);
(T) (A)
ctx。这可能是类型推断系统的一个限制。试试:ctx。你的问题表达得很好!SSCCE、错误消息等。上周的相关问题:鉴于我们不知道put
的实现,您怎么能认为这是正确的?那么它是类型安全的吗?因为在我看来,我可以将超类型层次结构中的所有实例作为值,这不是我想要允许的。我认为我们可以假设这是可以的,因为您必须记住,value
可以是T
的任何子类。因此,如果值
是一个字符串
,a
可以是属性
,属性
,或者现在的属性
。这唯一能防止的是从a
生成T
,这似乎是合理的。经过一段时间的思考后,听起来是合理的。这才是真正的解决方案,也是类型安全的,因为属性类型可以在类型层次结构中占据更高的位置。“它现在就像一个符咒,”马克·彼得斯-没关系,但不应该是必须的T
在推理过程中足够自由,因此属性
应该可以工作。顺便说一句,OP的代码是用Java8编译的。这个解决方案满足编译器的要求,但不满足最初创建的模式,该模式是为了避免像类型转换和显式类型参数这样的冗长提示。@iterator-您的原始代码现在用不同的推理规则在Java8中编译。然而,它也有可能在java7中工作,但是javac中有一个bug。不确定。
ctx.<List<?>, ListAttribute>put(ListAttribute.class, list);
(T) (A)