重写的方法在返回类型上是否有所不同?

重写的方法可以有 不同的报税表类别吗?

223011 次浏览

用于重写方法的 JavaSupports*协变返回类型。这意味着重写的方法可能具有特定于 更多的返回类型。也就是说,只要新的返回类型可以分配给要重写的方法的返回类型,就是允许的。

例如:

class ShapeBuilder {
...
public Shape build() {
....
}


class CircleBuilder extends ShapeBuilder{
...
@Override
public Circle build() {
....
}

这在 《 Java 语言规格说明书》第8.4.5节中有详细说明:

如果返回类型是引用类型,则在相互重写的方法之间返回类型可能会有所不同。返回类型可替换性的概念支持协变返回,即将返回类型专门化为子类型。

返回类型为 R1的方法声明 d1是返回类型为 R2的另一个方法 d2的返回类型可替换的,当且仅当以下条件成立:

  • 如果 R1为空,那么 R2为空。

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

  • 如果 R1是一个引用类型,那么:

    • R1是 R2的一个子类型,或者 R1可以通过未检查的转换(5.1.9)转换为 R2的一个子类型,或者

    • R1 = | R2 |

(“ | R2 |”指的是删除 R2,如 4.6的 JLS中所定义的那样。)


* 在 Java5之前,Java 有 不变返回类型,这意味着方法重写的返回类型需要与被重写的方法完全匹配。

是的,如果他们返回一个子类型,这里有一个例子:

package com.sandbox;


public class Sandbox {


private static class Parent {
public ParentReturnType run() {
return new ParentReturnType();
}
}


private static class ParentReturnType {


}


private static class Child extends Parent {
@Override
public ChildReturnType run() {
return new ChildReturnType();
}
}


private static class ChildReturnType extends ParentReturnType {
}
}

此代码编译并运行。

返回类型必须与声明的返回类型相同,或者是其子类型 在超类的原始重写方法中。

重写和返回类型,以及协变返回 < br/> 子类必须定义一个与继承版本完全匹配的方法。或者,在 Java5中,您可以更改 < br/> < h2 > 示例代码中的返回类型

                                                                                                            class Alpha {
Alpha doStuff(char c) {
return new Alpha();
}
}
class Beta extends Alpha {
Beta doStuff(char c) { // legal override in Java 1.5
return new Beta();
}
} } 
As of Java 5, this code will compile. If you were to attempt to compile this code with a 1.4 compiler will say attempting to use incompatible return type – sandeep1987 1 min ago

是的,它可能不同,但有一些限制。

在 Java 5.0之前,重写方法时,参数和返回类型必须完全匹配。Java 5.0它引入了一个新的工具叫做协变返回值类型。可以重写具有相同签名的方法,但返回返回对象的子类。

换句话说,子类中的方法可以返回一个对象,该对象的类型是该方法返回的类型的子类,该方法在超类中具有相同的签名。

是的,这是可能的

class base {


base show(){


System.out.println("base class");


return new base();


}
}


class sub extends base{


sub show(){


System.out.println("sub class");


return new sub();


}
}


class inheritance{


public static void main(String []args) {


sub obj=new sub();


obj.show();
}
}

有可能. . 返回类型只有在父类方法返回类型为
子类方法返回类型的超类型。
手段

class ParentClass {
public Circle() method1() {
return new Cirlce();
}
}


class ChildClass extends ParentClass {
public Square method1() {
return new Square();
}
}


Class Circle {


}


class Square extends Circle {


}


如果这是那么不同的返回类型可以允许..。

一般来说是的,覆盖方法的返回类型可以不同。但这并不简单,因为有些案子牵涉其中。

案例1: 如果返回类型是基元数据类型或 void。

输出: 如果返回类型为空或原语,那么父类方法和重写方法的数据类型应该是相同的。 例如,如果返回类型是 int,float,string,那么它应该是相同的

案例2: 如果返回类型是派生数据类型:

输出: 如果父类方法的返回类型是派生类型,则重写方法的返回类型与子类的派生数据类型相同。 例如,假设我有一个类 A,B 是 A 的一个子类,C 是 B 的一个子类,D 是 C 的一个子类; 然后如果超类返回类型 A,那么子类中的重写方法可以返回 A,或者 B/C/D 类型,也就是它的子类型。这也称为协方差。

其他的答案都是正确的,但是令人惊讶的是,这里所有的答案都忽略了理论方面: 返回类型可以不同,但是由于 Liskov代换原则的原因,它们只能使用超类中使用的类型 限制

它非常简单: 当你有调用某个方法的“客户端”代码时:

int foo = someBar.bar();

然后上面的代码必须工作(并且不管调用哪个 bar()实现都返回一个 int)。

意思是: 如果有一个 Bar 子类覆盖了 bar(),那么您仍然必须返回一些不会破坏“调用者代码”的内容。

换句话说: 假设基 bar()应该返回 int。然后一个子类可以返回 short-但是不能返回 long,因为调用者可以很好地处理 short值,但是不能返回 long

是的。重写的方法可能有不同的返回类型。

但是限制是,重写的方法必须具有实际方法的返回类型的更具体类型的返回类型。

所有的答案都给出了重写方法的例子,该方法的返回类型是实际方法的返回类型的子类。

例如:

public class Foo{


//method which returns Foo
Foo getFoo(){
//your code
}


}


public class subFoo extends Foo{


//Overridden method which returns subclass of Foo
@Override
subFoo getFoo(){
//your code
}


}

但是这不仅仅局限于子类。甚至实现接口的类也是接口的特定类型,因此可以是预期接口的返回类型。

例如:

public interface Foo{


//method which returns Foo
Foo getFoo();


}


public class Fizz implements Foo{


//Overridden method which returns Fizz(as it implements Foo)
@Override
Fizz getFoo(){
//your code
}


}

答案是肯定的,也不是。

取决于这个问题。这里的每个人都回答了关于 Java > = 5的问题,有些人提到 Java < 5没有协变返回类型。

实际上,Java 语言 spec > = 5支持它,但 Java 运行时不支持。特别是,没有更新 JVM 以支持协变返回类型。

当时被认为是一个“聪明”的举动,但最终却成为 Java 历史上最糟糕的设计决策之一,Java 5在没有修改 JVM 或类文件规范的情况下实现了一系列新的语言特性。相反,所有的特性都是在 javac 中用技巧实现的: 编译器为嵌套/内部类生成/使用普通类,为泛型生成类型擦除和强制转换,为嵌套/内部类私有“友谊”生成合成访问器,为外部‘ this’指针生成合成实例字段,为’生成合成静态字段。班级的文字等等。

而协变返回类型是 javac 添加的更多语法糖。

例如:

class Base {
Object get() { return null; }
}


class Derived extends Base {
@Override
@SomeAnnotation
Integer get() { return null; }
}

Javac 将在 Derived 类中输出两个 get 方法:

Integer Integer:Derived:get() { return null; }
synthetic bridge Object Object:Derived:get() { return Integer:Derived:get(); }


生成的桥方法(在字节码中标记为 syntheticbridge)实际上覆盖了 Object:Base:get(),因为对于 JVM 来说,具有不同返回类型的方法是完全独立的,不能相互覆盖。为了提供预期的行为,桥只是调用您的“真实”方法。在上面的例子中,javac 将使用@Some 注释对 Derived 中的桥方法和实方法进行注释。

请注意,您不能用 Java < 5手工编写这个解决方案,因为桥和 real 方法只在返回类型上有所不同,因此它们不能在 Java 程序中共存。但是在 JVM 世界中,方法返回类型是方法签名的一部分(就像它们的参数一样) ,所以这两个命名相同并带有相同参数的方法被 JVM 视为完全独立的,因为它们的返回类型不同,并且可以共存。

(顺便说一句,字段的类型类似于字节码中字段签名的一部分,所以在一个字节码类中有几个不同类型但命名相同的字段是合法的。)

因此,为了充分回答您的问题: JVM 不支持协变返回类型,但 javac > = 5在编译时用一层甜蜜的语法糖衣伪造了它。

class Phone {
public Phone getMsg() {
System.out.println("phone...");
return new Phone();
}
}


class Samsung extends Phone{
@Override
public Samsung getMsg() {
System.out.println("samsung...");
return new Samsung();
}
    

public static void main(String[] args) {
Phone p=new Samsung();
p.getMsg();
}
}