Java继承(方法覆盖和重载)

LiT*_*Tle 3 java methods inheritance 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 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!)
    }
}
Run Code Online (Sandbox Code Playgroud)

我有以下问题:

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

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

这很正常.毫无疑问.

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

NIN*_*OOP 8

1. klass对象是MyClass的实例.

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

2.为什么它从MyClass2类执行方法?

由于要调用say()的对象MyClass2,它执行say()MyClass2.预期的行为.

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

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

这不是重写方法.具有相同签名(名称,加上其参数的数量和类型)的子类中的实例方法和作为超类中的实例方法的返回类型会覆盖超类的方法.重写方法也可以返回返回类型的子类型通过重写的方法.这称为协变返回类型.您的方法签名是不同的.因此调用klass.print(),其中klass是一个MyClass参考将总是指代print()MyClass.

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

因为在编译时,编译器会验证您是否可以基于引用类型调用方法.这里引用类型是MyClass,因为MyClass没有定义anotherPrint(double),编译器抱怨.它是一个编译时检查.问题1,编译器验证klass.say("hi")并且它看到存在一个MyClass可以这种方式调用的方法.那时,它并不关心klass引用变量是否会在运行时引用MyClass对象或MyClass2对象.因此它奏效了.

您可以在这里参考这些Oracle的教程.