继承里面的重写问题(父类与子类方法重名时,调用的优先级问题)

1.父类对象与子类对象分别调用相同方法名的方法

class Person2{
    public void show(){
        System.out.println("父类Person2的show方法");
    }
    public void show1(){
        System.out.println("父类Person2的show1方法");
    }
}

class Student2 extends Person2{
    public void show(){
        System.out.println("子类Student2的show方法");
    }
    public void show1(){
        System.out.println("子类Student2的show1方法");
    }
}

public class OverrideDemo1 {
    public static void main(String[] args) {
        Student2 s = new Student2();
        s.show();
        s.show1();
        Person2 p = new Person2();
        p.show();
        p.show1();
    }
}


结果为
在这里插入图片描述
父类对象调用父类的方法,打印父类方法的两条语句
子类对象调用与父类同名的方法,优先调用子类自己重写后的方法,打印子类方法里面的两条语句

2. 父类方法和构造器调用被子类重写后的方法

class Person2{
    public void show(){
        System.out.println("父类Person2的show方法");
        show1();
    }
    public void show1(){
        System.out.println("父类Person2的show1方法");
        show1();
    }
}

class Student2 extends Person2{
    public void show(){
        super.show();
    }
    public void show1(){
        System.out.println("子类Student2的show1方法");
    }
}

public class OverrideDemo1 {
    public static void main(String[] args) {
        Student2 s = new Student2();
        s.show();
    }
}

在这里插入图片描述

这里通过子类对象调用子类的show方法,show方法的方法体内是super.show(); ,这句话的意思是调用父类的show()方法,父类的show方法里面是调用show1()方法。
那么问题来了,根据方法调用的优先级顺序,这里应该是优先调用本类的show1()方法。但是因为子类重写了父类的show1()方法,方法重写又叫覆盖,这里会调用子类的show1()方法,而不是父类的。

同理,在父类构造器中出现,被子类重写后的方法时,也是优先调用子类的方法

package test;

class Person2{
    Person2(){
        System.out.println("父类的构造方法");
        show();
    }
    public void show(){
        System.out.println("父类Person2的show方法");
    }
}

class Student2 extends Person2{
    Student2(){
        System.out.println("子类的构造方法");
        show();
    }
    public void show(){
        //super.show1();
        System.out.println("子类Student2的show方法");
    }
}

public class OverrideDemo1 {
    public static void main(String[] args) {
        new Student2();
        System.out.println("=======");
        new Person2();
    }
}

结果为
在这里插入图片描述
输出结果中的第二句是调用了子类的show方法
因为在调用子类的构造器之前,会先初始化父类的构造器,所以才会看到先打印了父类的构造方法,然后父类构造方法调用被子类重写后的show方法,最后才是子类的构造器输出结果并且调用子类的show方法

如果对为什么先调用父类构造器有点晕的话,可以看这篇博客(这个超链接指向的博客)的后半部分

当然,如果用父类对象直接调用父类的构造器或者方法,那么是不会调用子类中被重写的方法的,上面的例子的后半部分结果证明了构造器,下面这个例子证明了调用的是父类的方法

class Person2{
    public void show(){
        System.out.println("父类Person2的show方法");
        show1();
    }
    public void show1(){
        System.out.println("父类Person2的show1方法");
    }
}

class Student2 extends Person2{
    public void show(){
        //super.show1();
        System.out.println("子类Student2的show方法");
    }
    public void show1(){
        System.out.println("子类Student2的show1方法");
    }
}

public class OverrideDemo1 {
    public static void main(String[] args) {
        Person2 p = new Person2();
        p.show();
    }
}

在这里插入图片描述

父类对象调用父类的show方法,哪怕方法体中有 show1(); 也是调用父类自己的方法,而不是子类重写后的。

在子类用super调用父类的show1方法也一样,方法体中的 show1(); 语句会自动跳转到子类的show1()方法

package test;

class Person2{
    public void show(){
        System.out.println("父类Person2的show方法");
        show1();
    }
    public void show1(){
        System.out.println("父类Person2的show1方法");
        show1();
    }
}

class Student2 extends Person2{
    public void show(){
        super.show1();
        System.out.println("子类Student2的show方法");
    }
    public void show1(){
        System.out.println("子类Student2的show1方法");
    }
}

public class OverrideDemo1 {
    public static void main(String[] args) {
        Student2 s = new Student2();
        s.show();
    }
}

在这里插入图片描述

不过有一点要记住的是,super调用父类的show,show1方法后,这两个方法都被执行了,里面的内容会被打印,不过是方法体中的 show1(); 语句会跳转到子类的show1方法

从上面的这个结果也能看出来, super.show1(); 调用了父类的show1方法,打印了 “父类Person2的show1方法” 这句话。然后父类show1方法中的
在这里插入图片描述
语句调用了子类的show1方法,打印了 “子类Student2的show1方法这句话”
最后继续执行子类的show方法剩下的方法体部分,打印 “子类Student2的show方法” 这句话

一个例子

package test1;

public class Demo1 {
    class Father{
        int num = 11;
        Father(){
            System.out.println("父类构造器");
            show();

        }
        void show(){
            System.out.println("父类的show方法,并且num的值为"+num);
        }
    }
    class Son extends Father{
        //int num = 22;
        Son(int i){
            num = i;
            System.out.println("子类构造器");
            show();
        }
        void show(){
            System.out.println("子类的show方法,并且num的值为"+num);
        }
    }

    public static void main(String[] args) {
        Demo1 d = new Demo1();
        d.new Son(10);
        System.out.println("==============");
        d.new Father();
    }
}

在这里插入图片描述
在调用子类构造器之前,会先初始化父类的构造器,所以第一句话打印的是*“父类构造器”*

父类构造器里面通过 show(); 调用了子类的show()方法,此时子类的构造器还没有初始化,所以是继承父类的num值,num值为11。所以第二句是*“父类的show方法,并且num的值为11”*

父类构造器初始化完毕之后,才开始执行子类的构造器,所以打印第三句,”子类构造器“

之后子类构造器自己调用自己的show方法,并且num值变成了创建对象时传入的值10,所以第四句话是*”子类的show方法,并且num的值为10”*

总结一下
  1. 子类调用构造方法时,不论是有参还是无参构造,都是默认访问父类的无参构造方法
    父类构造方法中的语句执行完毕后,才会执行子类构造方法中的语句
    (可以用super(参数列表)的方式,改变要先初始化的父类构造方法)
  2. 子类调用构造方法,初始化父类时,父类的构造方法会调用子类重写后的重名方法
  3. 子类用super调用父类方法时,父类方法会调用子类重写后的重名方法
  4. 父类自身调用构造方法和普通方法时,都是访问自身的方法,不会访问子类的同名方法

我写了一段比较绕的代码当最后总结的例子

package review;

class Father{
    public int age = 30;
    {
        System.out.println("父类构造代码块");
    }
    public Father(){
        System.out.println("父类无参构造方法");
        Show();
    }
    public void Show(){
        System.out.println("父类的方法一");
        Show2();
    }
    public void Show2(){
        System.out.println("父类的方法二");
    }
}

class Son extends Father{
    {
        System.out.println("子类的构造代码块");
    }
    public Son(){
        System.out.println("子类的无参构造方法"+"---"+age);
    }
    public Son(int age){
        System.out.println("子类的有参构造方法"+"---"+age);
    }

    public void Show(){
        System.out.println("子类的方法一");
        super.Show2();
    }
    public void Show2(){
        System.out.println("子类的方法二");
    }
}
public class extendsDemo {
    public static void main(String[] args) {
        Son s = new Son(10);
        System.out.println("---------");
        Father f = new Father();

    }
}

在这里插入图片描述

  • 11
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一纸春秋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值