当前位置: 首页 > 知识库问答 >
问题:

协变返回类型是否根据jls重写?

谷梁晟
2023-03-14

就说,我问题的重点是学会理解jls。我相信jls中的一切都是真的。

考虑JLS下一个片段:

8.4.8.1。重写(通过实例方法)

在类C中声明的实例方法m1重写在类A中声明的另一个实例方法m2,前提是以下所有条件均为真:

C是a的一个子类。

m1的签名是m2签名的子签名(§8.4.2)。

要么:

m2是公共的、受保护的或在与C相同的包中声明具有默认访问权限的,或者

m1覆盖方法m3(m3不同于m1,m3不同于m2),因此m3覆盖m2。

此外,如果m1不是抽象的,那么可以说m1实现了它重写的抽象方法的任何和所有声明。

转到子签名声明:

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

m2与m1具有相同的签名,或

m1的签名与m2签名的删除(§4.6)相同。

关于相同的签名:

如果两个方法具有相同的名称和参数类型,则它们具有相同的签名。

哪条规则允许使用协变返回类型?

共有1个答案

涂羽
2023-03-14

这些规则都不允许协变量返回类型。方法的签名引用方法名称及其参数的类型和顺序,但不引用返回类型。

来自JLS,第8.4.8.3节:

如果具有返回类型R1的方法声明d1重写或隐藏了具有返回类型R2的另一个方法d2的声明,则d1必须是d2的返回类型可替换的(§8.4.5),否则会发生html" target="_blank">编译时错误。

此规则允许协变返回类型—在重写方法时优化方法的返回类型。

参见第8.4.5节,其中规定:

如果满足以下任一条件,则返回类型为R1的方法声明d1为返回类型,可替换为另一个返回类型为R2的方法d2:

>

  • 如果R1无效,那么R2无效。

    如果R1是基元类型,则R2与R1相同。

    如果R1是引用类型,则以下情况之一为真:

    >

  • R1适用于d2的类型参数(§8.4.4),是R2的一个子类型。

    R1可以通过未经检查的转换(§5.1.9)转换为R2的子类型。

    d1不具有与d2相同的签名(§8.4.2),并且R1=|R2|。

    (强调我的)

    我加粗的那部分允许协变返回类型。

  •  类似资料:
    • 问题内容: Java中的协变返回类型是什么?在一般的面向对象编程中? 问题答案: 协变返回,意味着当一个方法被覆盖时,覆盖方法的返回类型被允许为覆盖方法的返回类型的子类型。 为了举例说明,通常情况是-声明为返回类型。你可以在自己的类中重写此方法,如下所示: 这样做的好处是,任何持有对MyFoo对象的显式引用的方法都将能够调用clone()并知道(无需强制转换)返回值是的实例。如果没有协变量返回类型

    • 本文向大家介绍Java中的协变返回类型,包括了Java中的协变返回类型的使用技巧和注意事项,需要的朋友参考一下 协变返回类型是指重写方法的返回类型。它允许缩小重写方法的返回类型,而无需强制转换类型或检查返回类型。协变返回类型仅适用于非原始返回类型。 从Java 5开始,仅通过遵守返回类型是重写的方法返回类型的子类的条件,就可以通过更改其返回类型来覆盖方法。 示例 以下示例展示了相同的内容。 输出结

    • 我为协变返回类型的继承创建了一个小示例。基本上有三种不同的类别: 主应用程序: BaseManager: 鸟经理: 当我重写方法以返回时,为什么我需要将类型转换为? 我使用过的重写方法在返回类型上会有所不同吗?作为参考。 编辑: 我有不同的子模型,它们都继承自。所有模型都允许存在一次。我尝试将这些模型添加到列表中,而不是对每个模型使用单例。使用,我想得到实际的模型。也许我得考虑太多了。

    • 这将无法编译,因为编译器只能保证是的某个子类,但不能保证的每个子类都将重写以返回自身的数组,就像我碰巧对所做的那样,因此Java只知道返回而不是。 我如何保证每个子类都用一个协变返回类型重写,以便我可以将它与泛型一起使用?

    • 问题是,如果我执行上述^,以访问endpoint上的请求信息,则如果筛选器验证失败,我就不能再中止筛选器中的请求,因为我会得到以下错误: 似乎如果您在Jerseyendpoint上定义任何类型的参数,这些参数可以在ContainerRequestContext中访问,那么它将不允许您中止过滤器中的过滤器链。 一个解决方法(我还没有尝试过,但假设会成功)是这样做:如果过滤器验证失败,我可以只向请求添

    • 我有下面的课,我试图测试。我遇到问题的方法是,因为我试图存根/模拟行为,然后在测试中验证行为。