下面是一个极简主义的例子

import java.util.List;

public class SomeClass {
    interface SuperType {
    }

    static class SubType implements SuperType {
    }

    interface SuperTypeProcessor {
        void processSubtypesOfSupertype(List<? extends SuperType> superTypes);

        List<? extends SuperType> getSubtypesOfSupertype();
    }

    static class ConcreteSuperTypeProcessor implements SuperTypeProcessor {
        // doesn't override!
        @Override
        public void processSubtypesOfSupertype(List<SubType> superTypes) {
        }

        // DOES override!
        @Override
        public List<SubType> getSubtypesOfSupertype() {
            return null;
        }
    }
}

我以为List<SubType>总是List<? extends SuperType>的一个子类.也许,它是is,但我需要重新审视凌驾的规则吗?

让我们来看看文档says

在类C中声明的一个实例方法m1覆盖了在类A中声明的另一个实例方法m2,当且仅当以下条件都为真:

C是A.✅的子类.

M1的签名是m2的签名的子签名(§8.4.2).🤔

以下任一项:

M2是公共的、受保护的或在与C或✅相同的包中使用默认访问权限声明的

M1覆盖方法M3(M3不同于M1,M3不同于M2),因此M3覆盖M2.

什么是子签名?

方法m1的签名是方法m2的签名的子签名,如果:

M2具有与M1或❌相同的签名

M1的签名与删除m2的签名相同(第4.6节).🤔

什么是签名擦除?

类型擦除是从类型(可能包括参数类型和类型变量)到类型(从不是参数类型或类型变量)的映射.我们将类型T的擦除写为|T|.擦除映射定义如下:

参数类型(§4.5)G&lt;T1,...,TN&gt;的擦除是|G|.

嵌套类型T.C的擦除是|T|.C.

数组类型T[]的擦除是|T|[].

类型变量的擦除(§4.4)是对其最左侧界限的擦除.🤔

所有其他类型的擦除就是类型本身.

这肯定意味着

  • void processSubtypesOfSupertype(List<? extends SuperType>)被擦除为void processSubtypesOfSupertype(List<SuperType>)
  • List<? extends SuperType> getSubtypesOfSupertype()被抹go 成List<SuperType> getSubtypesOfSupertype()

如果是这样,那么为什么List<SubType> getSubtypesOfSupertype()是有效覆盖?根据我的定义,List<SubType> getSubtypesOfSupertype()是(类型擦除的)List<SuperType> getSubtypesOfSupertype()的子签名not

我错过了什么?

推荐答案

这是正常的,与泛型无关.

子类必须能够做到它们的父类所能做到的everything.超类说它可以用anyList<? extends Supertype>pprocessSubtypesOfSupertype个.任何这样的列表都可以传入.

如果你只能 payable List<Subtype>分,那你就做不到.

最后,为了纠正您的困惑,Java中的擦除没有泛型.void processSubtypesOfSupertype(List<? extends SuperType>)被抹go 成void processSubtypesOfSupertype(List).

Java相关问答推荐

PostgreSQL货币兑换率查询

无法在org. openjfx:javafx—fxml:21的下列变体之间进行 Select

蒙蒂霍尔比赛结果不正确

使用UTC时区将startDatetime转换为本地时间

JOOQ中的子查询使用的是默认方言,而不是配置的方言

格式中的特定回录键-值对

为什么同步数据块无效?

%This内置函数示例

Java泛型类方法的静态返回类型是否被类型擦除?

如何读取3个CSV文件并在控制台中按顺序显示?(Java)

如果List是一个抽象接口,那么Collectors.toList()如何处理流呢?

如何在EL处理器中定义带有命名空间的变量?

项目react 堆中doOnComplete()和Subscribe()的第三个参数之间的差异

如何在ImageIO或十二只猴子中旋转TIFF CMYK图像?

使用for循环时出现堆栈溢出错误,但如果使用if块执行相同的操作,则不会产生错误

Oracle中从JSON中提取和插入数据

在具有Quarkus Panache的PostgreSQL中将JSON数据存储为JSONB时,会将其存储为转义字符串

";home/runner/work/中没有文件...匹配到[**/pom.xml];Maven项目的构建过程中出现错误

多线程、并发和睡眠未按预期工作

java 11上出现DateTimeParseException,但java 8上没有