我有两节课:
class ProblematicConverter implements Converter<List<?>> {};
class NonProblematicConverter implements Converter<List> {};
类Utils的方法:
<T> void addConverter(Class<? extends T> cls, Converter<T> converter);
现在,第一个函数调用正常,但第二个产生错误:
addConverter(List.class, new ProblematicConverter());
addConverter(List.class, new NonProblematicConverter());
错误说:
&#34; Utils类型中的方法addConverter(Class,Converter)不适用于参数(Class,ProblematicConverter)&#34;
我不明白为什么会这样。
答案 0 :(得分:1)
根据你的评论,我认为在这里做正确的事情可能是在List.class
上使用未经检查的强制转换,但首先,问题中的代码无法编译的原因大致是:
T
addConverter
被推断为List<?>
。cls
中的有界通配符要求其类型参数为T
或子类型为T
,但原始类型List
是List<?>
的超类型}(specified here)。Class<List>
与cls
的{{1}}的推断类型不兼容。因此,例如,以下两个声明中的任何一个都将使用问题中的调用进行编译:
Class<? extends List<?>>
这当然不能帮到你,但它说明了<T> void m(Class<T> cls, Converter<? extends T> converter) {}
<T> void m(Class<? super T> cls, Converter<T> converter) {}
和List
之间的关系。
所以,无论如何,根据你的评论说你试图消除原始类型并且不能改变List<?>
的声明,可能适当的是使用来自addConverter
的未经检查的演员表到Class<List>
:
Class<List<?>>
这将允许您致电例如:
@SuppressWarnings("unchecked")
static final Class<List<?>> WILD_LIST =
(Class<List<?>>) (Class<? super List<?>>) List.class;
但是,我想指出未经检查的强制转换不是通用解决方案。这是解决这个特定转换问题的解决方案。 addConverter(WILD_LIST, new ProblematicConverter());
到Class<GenericType>
。这样做是安全的,因为Class<GenericType<?>>
是一种比原始类型GenericType<?>
更具限制性的类型,并且因为GenericType
对其类型参数的处理范围非常有限。
如果你可以更改Class
的声明,我想我会建议使用像Guava addConverter
而不是TypeToken
之类的东西,因为那时你没有这种问题。