添加通配符时,方法不适用于参数

时间:2017-06-07 14:25:29

标签: java generics compiler-errors

我有两节课:

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;

我不明白为什么会这样。

1 个答案:

答案 0 :(得分:1)

根据你的评论,我认为在这里做正确的事情可能是在List.class上使用未经检查的强制转换,但首先,问题中的代码无法编译的原因大致是:

  • T addConverter被推断为List<?>
  • cls中的有界通配符要求其类型参数为T或子类型为T,但原始类型ListList<?>的超类型}(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之间的关系。

您可能还会看到我these两个answers讨论类似情况。

所以,无论如何,根据你的评论说你试图消除原始类型并且不能改变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之类的东西,因为那时你没有这种问题。