Java继承(方法重写和重载)

Java继承(方法重写和重载),java,inheritance,methods,overriding,Java,Inheritance,Methods,Overriding,除了Java继承是该语言的一个基本特性之外,我还有一些问题。 以下是我的测试示例的来源: class MyClass{ public void say(String t){ System.out.println("Hello MyClass "+t); } public void print(MyClass t){ System.out.println("MyClass is printed"); } public v

除了Java继承是该语言的一个基本特性之外,我还有一些问题。
以下是我的测试示例的来源:

class MyClass{

    public void say(String t){
        System.out.println("Hello MyClass "+t);
    }

    public void print(MyClass t){
        System.out.println("MyClass is printed");
    }

    public void anotherPrint(int i){
        System.out.println("MyClass is printed again");
    }
}

class MyClass2 extends MyClass{

    public void say(String t){
        System.out.println("Hello MyClass2 "+t);
    }

    public void print(MyClass2 t){
        System.out.println("MyClass2 is printed");
    }

    public void anotherPrint(double i){
        System.out.println("MyClass2 is printed again");
    }
}

public class HelloWorld{

    public static void main(String []args){
        MyClass klass = new MyClass2();

        klass.say("h"); //Question 1 (Prints: "Hello MyClass2 h")

        klass.print(new MyClass2()); //Question 2 (Prints: "MyClass is printed")
        klass.print(new MyClass()); //Question 3 (Prints: "MyClass is printed")

        klass.anotherPrint(1); //Question 4 (Prints: "MyClass is printed again")
        klass.anotherPrint(1.0); //Question 5 (Throws Exception!)
    }
}
我有以下问题:

1.klass对象是
MyClass
的实例。它为什么从
MyClass2
类执行方法?

2,3 . 在问题1中,klass调用
MyClass2
类的方法。在这里,我使用了一个适合每个重写和重载(同时)方法的参数。为什么klass对象总是从
MyClass
类调用方法?

4.这是正常的。没问题。

5.抛出异常是正确的。klass对象没有此双参数方法。但是,为什么不从
MyClass2
类调用该方法,就像在问题1中发生的那样?

1。klass对象是MyClass的实例

不,它是类型为
MyClass
的引用变量,但引用的是
MyClass2的对象。

二,。为什么它要执行MyClass2类中的方法

由于您正在对
MyClass2
的对象调用
say()
,因此它执行
MyClass2
say()
。预期的行为

这在Java中称为运行时多态性。这提供了覆盖类层次结构树中已有功能的能力。在运行时,将调用方法的哪个版本取决于存储在该引用变量中的实际对象的类型,而不是引用变量的类型

三,。在问题1中,klass调用Class2类的方法。在这里,我使用了一个适合每个重写和重载(同时)方法的参数。为什么klass对象总是从MyClass类调用该方法

这不是重写的方法。子类中具有相同签名(名称及其参数的编号和类型)且返回类型作为超类中实例方法的实例方法将覆盖超类的方法。重写方法还可以返回被重写方法返回的类型的子类型。这称为协变返回类型。您的方法签名不同。因此调用
klass.print()
其中
klass
MyClass
引用将始终引用
MyClass
print()

四,。抛出异常是正确的。klass对象没有此双参数方法。但是,为什么不从MyClass2类调用该方法,就像在问题1中发生的那样

因为在编译时,编译器会验证您是否可以基于引用类型调用方法。这里的引用类型是
MyClass
,由于
MyClass
没有定义另一个打印(double),编译器抱怨。这是一个编译时检查。在问题1中,编译器验证了
klass.say(“hi”)
,并且发现
MyClass
中存在一个可以通过这种方式调用的方法。当时,它并不关心
klass
引用变量是否会在运行时引用
MyClass
对象或
MyClass2
对象。因此它起了作用


您可以参考这些Oracle教程。

问题1:-行MyClass klass=new MyClass2();您已经完成了向上转换,捕获了子类的引用id(对象)。在向上转换的情况下,将调用子类的方法。
虽然编译器在编译时检查父级中的say()函数,但在运行时编译器发现子级中也有say()函数,因此它将其与子类方法绑定并调用它。这就是问题1的输出为Hello MyClass2 h的原因。一个类的实例将有其父类的方法加上它自己的方法。如果其中一个子类的签名与父类中某个方法的签名相同,则将重写它

在本例中,MyClass2的一个实例将具有以下方法:

public void say(String t) //From MyClass2 (override)
public void print(MyClass2 t)
public void anotherPrint(double i)
public void print(MyClass t) //Inherited from MyClass
public void anotherPrint(int i) //Inherited from MyClass
但是您将klass声明为MyClass,因此它将具有可用的此方法

public void say(String t) //From MyClass
public void print(MyClass t)
public void anotherPrint(int i)
现在,回答你的问题

1-调用MyClass的方法。但在运行时,klass实际上是MyClass2的一个对象,MyClass2重写了这个方法,因此它将从MyClass2调用这个方法

2,3-调用MyClass的print方法。在运行时,klass来自MyClass2,但MyClass2不重写此方法。签名不同。所以要调用的是MyClass。使用MyClass2对象作为参数可以很好地工作,因为MyClass2是MyClass


5-MyClass没有任何名为anotherPrint的方法在Java中接收双方法重载和方法重写是Java中的两个重要概念,它允许Java程序员用相同的名称声明方法,但行为不同。方法重载和方法重写基于Java中的多态性。在方法重载的情况下,同名的方法在同一类中共存,但它们必须具有不同的方法签名,而在方法重写的情况下,在派生类或子类中声明同名的方法。方法重载在编译时使用Java中的静态绑定解决,而方法重写在运行时使用Java中的动态绑定解决。简言之,当您在Java中重载一个方法时,它的方法签名被更改,而在重写方法的情况下,签名保持不变,但一个方法只能在子类中被重写。由于Java支持多态性并在运行时解析对象,所以它能够在Java中调用重写的方法


阅读更多内容:

最后,我相信,我理解了何时调用重写的方法。但是我相信参数为“MyClass2”的方法满足了需求,应该调用这个方法