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

为什么java不允许在方法覆盖的情况下改变返回类型

许永年
2023-03-14

我的A类是:

 public class A {
    int sayHello(int i,int j){
        return i+j;
    }
 }

另一类B为:

public class B extends A {  
    @Override
    int sayHello(int i, int j) {
        return i+j;
    }
}

如果我将类A的方法sayHello(int,int)的返回类型从int改为float,它会显示一个错误,因为根据覆盖规则,返回类型也被认为是无效的覆盖和重载。

我不明白为什么java不允许更改返回类型。为什么返回类型也需要相同

共有3个答案

邵旺
2023-03-14

如图所示(强调我自己)

子类覆盖方法的能力允许类从行为“足够接近”的超类继承,然后根据需要修改行为。重写方法与它重写的方法具有相同的名称、参数数量和类型以及返回类型。重写方法也可以返回被重写方法返回的类型的子类型。这种子类型称为协变返回类型。

如果返回的类型不同,它会破坏其他类,这些类可以在运行时使用多态性来检测类的类型。

慕迪
2023-03-14

重写方法时可以更改返回类型:只需使用协变类型重写它即可。

例如,如果您将接口定义为:

interface Foo {
  Object foo();
}

那么可以这样实施它:

class Bar implements Foo {
  @Override public String foo() {
    return "";
  }
}

因为Foo的所有实现。foo()必须返回一个Objects,并且所有Strings都是 s。

但是,不能用另一种方法:如果返回类型Foo。foo()String,您无法实现它来返回Object,因为该方法的调用方需要能够在该实例上调用 的方法。例如:

void test(Foo instance) {
  System.out.println(instance.foo().length());
}

如果返回了 Object,这在运行时将不起作用,因为 Object 上没有 length() 方法。(但更具体地说,它必须是 String.length() 方法,而不仅仅是任何长度方法:Java 不支持鸭子类型)。编译器可以检测到这种不匹配,因此它会阻止您执行此操作。

int没有类型协变(或任何原始类型),因此当您覆盖返回int的方法时,您必须返回int

允许这样做的理论原因是Liskov替换原则,它可以解释为“子类型方法可以在它们接受的参数中更通用,在它们返回的类型中更具体”。

但是,Java不允许使用更通用的参数类型,因为它解决方法重载的方式。

楚宇
2023-03-14

因为:

class Parent {
    int method() { return 1; }
}

class Child extends Parent {
    float method() { return 1.0f; }
}

Parent p = new Child();
int myInt = p.method();

method()返回什么?它应该是一个int,因为家长说它是一个int。但是儿童返回一个浮点数。那么你希望发生什么?JVM应该崩溃吗?

顺便说一下,你可以改变返回类型,但它必须是类型的子类型,被覆盖的方法返回。因此,您可以重写返回< code>Parent的方法,并使用< code>Child作为返回类型。

 类似资料:
  • 问题内容: 为什么无法覆盖静态方法? 如果可能,请使用示例。 问题答案: 覆盖取决于拥有类的实例。多态性的重点是可以对一个类进行子类化,并且实现那些子类的对象对于在超类中定义的相同方法(在子类中被重写)将具有不同的行为。静态方法未与类的任何实例相关联,因此该概念不适用。 影响Java设计的因素有两个。一个是对性能的关注:Smalltalk批评它太慢(垃圾回收和多态调用是其中的一部分),Java的创

  • 问题内容: 作为ASP.NET MVC 2 Beta 2更新的一部分,默认情况下不允许JSON GET请求。看来您需要将字段设置为从控制器返回对象之前。 这背后的原因是什么?如果我正在使用JSON GET尝试进行一些远程验证,那么我应该使用其他技术吗? 问题答案: DenyGet默认的原因是在MSDN上,该链接提供了Phil Haack的博客 的详细信息。看起来像跨站点脚本漏洞。

  • 我最近在浏览SurfaceView的android文档,我发现要获得实际的surface,你必须做以下事情: surface holder的文档在这里:https://developer . Android . com/reference/Android/view/surface holder . html 现在一个SurfaceHolder从getHolder()返回,然后你可以在那个支架上调用

  • 问题内容: 这是我的代码,但是我没有得到方法如何接受类型作为返回值。如何运作?谁能解释一下这种方法的工作原理? 提前致谢 :) 问题答案: 好的,所以首先要做的是: 这是一个不断扩大的原始类型转换,因此这是合法的。您可以: 但是您不能: 第二:它返回的根本不是ASCII码。Java执行Unicode。 碰巧的是,当创建Java时,Unicode仅定义了适合16位的代码点。因此,它被创建为2字节的无

  • 如果我在java中有一个抽象的(或据我所知的)超类,如下所示: 我注意到,在重写这个方法时,子类可以使用自身作为返回类型,但不能使用参数: 为什么不允许这样做?我不是在寻求解决方案——我知道我可以在方法中使用< code>instanceof检查或其他方法,我更想知道为什么前者是可以接受的,而后者对编译器来说却不是。

  • 为什么允许使用memcpy指针更改常量变量? 此代码: 编译时只包含一个警告: 警告:传递“memcpy”的参数 1 将丢弃指针目标类型中的“const”限定符 [默认启用] 但运行得很好,并更改了常量变量的值。