【问题标题】:Generics with Wildcards (Map<? extends A, List<? extends B>>)带有通配符的泛型(Map<? extends A, List<? extends B>>)
【发布时间】:2014-04-08 08:41:48
【问题描述】:

考虑以下代码:

public interface A {};

public class AImpl implements A {};

public interface B {};

public class BImpl implements B {};

public interface Service{
  Map<? extends A, List<? extends B>> get();
}

为什么下面Service的实现不能编译?

public class ServiceImpl implements Service {
  public Map<AImpl, List<BImpl>> get() {
    return null;
  }
}

编译器错误:

返回类型与Service.get()不兼容

但是下面的代码编译:

public interface Service{
   List<? extents B> get();
}

public class ServiceImpl implements Service{
   public List<BImpl> get(){
       return null;
   }
}

【问题讨论】:

  • 错误说明了什么? (我认为你想在最后一个代码 sn-p 中扩展而不是实现)
  • 我假设extent 应该是extends?您还缺少一些&gt;s。请复制/粘贴您在 IDE 中测试过的实际代码。另外,包括您的编译器错误。你不这样做浪费了很多人的时间。
  • *在Map&lt;? extent A, List&lt;? extent B&gt; get()中的范围......它是extends,先修复它看看。

标签: java list generics map


【解决方案1】:

因为&lt;? extends BaseType&gt; 表示“一些未指定的子类型BaseType”,而class Sub extends BaseTypeBaseType 的子类型,不是吗。阅读Java Generics FAQ,尤其是从Wildcard Capture部分开始,了解更多详情。

你应该正确地生成你的代码:

public interface Service<K extends A, V extends B> {
    Map<K, List<V>> get();
}

public class ServiceImpl implements Service<AImpl, BImpl> {
    @Override
    public Map<AImpl, List<BImpl>> get() {
        return null;
    }
}

【讨论】:

  • 我想说这显然是错误的:List&lt;AImpl&gt;List&lt;? extends A&gt; 的子类型,所以A 不是问题。问题更深一层,即在List 参数中(见我的回答)。但我正在等待我的反对票,因为泛型很复杂;-)
  • 您的示例也可以编译。区别在于您是否需要通用 Service 接口(我的示例)或不需要(您的示例)。
  • 其意图可能是没有Service 接口的类型参数(并且它们不是必需的,至少根据最初的代码草图可以这么说...... )。无论如何,它没有编译的原因A无关。
【解决方案2】:

Service#get()方法的返回类型指定为

Map<? extends A, List<? extends B>> get();

而你正试图返回一个

Map<AImpl, List<BImpl>> 

您可以使用协变返回类型。似乎您认为这里就是这种情况。但问题是这种协方差不适用于泛型类型参数。虽然List&lt;BImpl&gt;List&lt;? extends B&gt; 的子类型,但这并不意味着Map&lt;AImpl, List&lt;BImpl&gt;&gt;Map&lt;? extends A, List&lt;? extends B&gt;&gt; 的子类型。

一个结构相似但更简单的情况是List&lt;Integer&gt; 不是List&lt;Number&gt; 的子类型。

您可以将Service 接口中的返回类型更改为

Map<? extends A, ? extends List<? extends B>> get();

让它工作。

【讨论】:

    【解决方案3】:

    ServiceImpl 不能是接口,因为您的实现不能在接口中;将其更改为基类并尝试一下。

    【讨论】:

      【解决方案4】:

      你写什么?

      Map<? extents A, List<? extents B> get();
      

      java对extents一无所知

      至少使用extends

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-08-13
        • 1970-01-01
        • 2014-06-08
        • 1970-01-01
        • 1970-01-01
        • 2016-10-11
        • 2022-12-17
        • 2018-10-04
        相关资源
        最近更新 更多