【问题标题】:"Attempting to use incompatible return type" with class implementing Serializable“尝试使用不兼容的返回类型”与实现 Serializable 的类
【发布时间】:2019-10-15 09:13:44
【问题描述】:

我有如下界面:

切片器

public interface Slicer {
    Optional<Map<String, ? extends Serializable>> pointer();
}

我有一个实现:

DynamoDbSlicer

public abstract class DynamoDbSlicer implements Slicer {

    @Override
    public abstract Optional<Map<String, AttributeValue> pointer();
}

其中AttributeValue 来自 AWS 开发工具包并定义为:

public final class AttributeValue implements SdkPojo, Serializable, ToCopyableBuilder<AttributeValue.Builder, AttributeValue> {

注意它实现了Serializable

我在DynamoDbSlicer 中的抽象方法上遇到编译器错误:

pointer() in DynamoDbSlicer clashes with pointer() in Slicer; attempting to use incompatible return type

我错过了什么?

【问题讨论】:

  • 根据PECS可以试试super吗?

标签: java generics inheritance types


【解决方案1】:

乍一看,它应该可以编译,因为 Java(从 1.5 开始)具有返回类型协变。这意味着覆盖方法可以声明一个返回类型,它是原始方法返回类型的子类型。

看起来Optional&lt;Map&lt;String, Serializable&gt;&gt;Optional&lt;Map&lt;String, ? extends Serializable&gt;&gt; 的子类型,但事实并非如此。有趣的是,如果您从两种返回类型中删除 Optional 部分,则会编译。

interface Slicer {
    Map<String, ? extends Serializable> pointer();
}
abstract class DynamoDbSlicer implements Slicer {
    @Override
    public abstract Map<String, Serializable> pointer();
}

它可以编译是因为Map&lt;String, Serializable&gt;Map&lt;String, ? extends Serializable&gt; 的子类型——可以将前者的实例分配给后者类型的变量。

但是,添加Optional 会导致编译失败,原因与a List&lt;Dog&gt; isn't a List&lt;Animal&gt; 相同——泛型是不变的。在这个类比中,Dog 类似于匹配Map&lt;String, Serializable&gt; 的特定子类型,Animal 类似于匹配Map&lt;String, ? extends Serializable&gt; 的一般类型。就像List&lt;Dog&gt; 不是List&lt;Animal&gt;Optional&lt;Map&lt;String, Serializable&gt;&gt; 不是Optional&lt;Map&lt;String, ? extends Serializable&gt;&gt;

在不删除Optional 位的情况下编译它的最简单方法是完全匹配类型。

abstract class DynamoDbSlicer implements Slicer {
    @Override
    public abstract Map<String, ? extends Serializable> pointer();
}

如果这不符合您的要求,那么您需要在您的类可以作为类型参数提供的接口上创建一个类型参数。

interface Slicer<T extends Serializable> {
    Optional<Map<String, T>> pointer();
}
abstract class DynamoDbSlicer implements Slicer<AttributeValue> {
    @Override
    public abstract Optional<Map<String, AttributeValue>> pointer();
}

类型参数允许它编译。

【讨论】:

  • 感谢您的解释!我想我可以在没有可选的情况下使代码工作
  • 在“有趣”部分,“删除可选部分”是指接口中的返回类型为Map&lt;String, ? extends Serializable&gt;,类中的Map&lt;String, AttributeValue&gt; 将编译。
猜你喜欢
  • 2016-11-24
  • 2020-06-08
  • 2014-08-29
  • 2016-05-28
  • 2015-09-01
  • 1970-01-01
  • 2019-09-06
  • 2013-11-11
  • 2016-02-14
相关资源
最近更新 更多