【问题标题】:Method is not applicable for arguments when adding wildcard添加通配符时方法不适用于参数
【发布时间】:2017-06-07 23:16:27
【问题描述】:

我有以下两个课程:

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());

错误提示:

“Utils类型中的方法addConverter(Class, Converter)不适用于参数(Class, ProblematicConverter)”

我不明白为什么会这样。

【问题讨论】:

  • List 不是List&lt;?&gt; 的子类型。 (实际上是另一种方式。)你想在这里做什么?在我看来,您似乎不太可能按原样工作。您需要使用 Guava TypeToken 之类的东西,否则会真正放松 addConverter 的声明。
  • Listraw type 和 ?是wildcard,除非您完全知道自己在做什么,否则您应该避免使用其中任何一种。 (在可能的情况下首选&lt;T extends SpecificClass&gt;
  • @Radiodef 函数 addConverter 由第三方库提供,我无法更改。我必须实现实现转换器的类。当我使用 NonProblematicImplementation 时一切都很好,但我收到有关原始 List 类型的编译器警告。所以我开始纠正我的代码中的警告。

标签: java generics compiler-errors


【解决方案1】:

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

  • TaddConverter 被推断为 List&lt;?&gt;
  • cls 中的有界通配符要求其类型参数为TT 的子类型,但原始类型ListList&lt;?&gt; (specified here) 的超类型。
  • 因此,Class&lt;List&gt; 与推断的cls 类型不兼容,即Class&lt;? extends List&lt;?&gt;&gt;

因此,例如,以下两个声明中的任何一个都可以与问题中的调用一起编译:

<T> void m(Class<T> cls, Converter<? extends T> converter) {}
<T> void m(Class<? super T> cls, Converter<T> converter) {}

这当然不能帮助你,但它说明了ListList&lt;?&gt; 之间的关系。

你可能还会看到我的两个theseanswers,它们讨论了类似的情况。

所以无论如何,根据您的评论说您正在尝试消除原始类型并且无法更改 addConverter 的声明,可能合适的是使用从 Class&lt;List&gt;Class&lt;List&lt;?&gt;&gt; 的未经检查的强制转换:

@SuppressWarnings("unchecked")
static final Class<List<?>> WILD_LIST =
    (Class<List<?>>) (Class<? super List<?>>) List.class;

这会让你打电话,例如:

addConverter(WILD_LIST, new ProblematicConverter());

但是,我想指出,未经检查的强制转换不是通用 解决方案。这是解决这个特定转换问题的方法,例如Class&lt;GenericType&gt;Class&lt;GenericType&lt;?&gt;&gt;。这样做是安全的,因为 GenericType&lt;?&gt; 是比原始类型 GenericType 更具限制性的类型,并且因为 Class 可以使用其类型参数做的事情范围非常有限。

如果您可以更改addConverter 的声明,我想我建议您使用类似 Guava TypeToken 而不是Class,因为那样您就不会遇到此类问题。

【讨论】:

  • 小修正list.getClass()返回Class类型的变量
猜你喜欢
  • 1970-01-01
  • 2021-05-26
  • 1970-01-01
  • 1970-01-01
  • 2018-07-19
  • 2012-08-30
  • 2015-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多