当实例化一个继承自抽象类的子类时代码执行顺序

当实例化一个继承自抽象类的子类时,Java会调用父类的构造函数,并根据继承链进行初始化。这包括父类的字段初始化、初始化块和构造函数。父类中的方法(包括被子类重写的方法)也可能会在这个过程中被调用。以下是详细分析及代码示例。

详细分析

  1. 调用父类构造函数

    • 在实例化子类时,首先调用父类的构造函数。
    • 父类构造函数的调用是由子类构造函数中的super()显式或隐式调用。
  2. 初始化父类字段和代码块

    • 在调用父类构造函数之前,父类中的字段和初始化块会被执行。
  3. 调用父类方法

    • 父类的构造函数和初始化块可以调用父类的方法。如果这些方法在子类中被重写,则在这些调用中会执行子类重写的方法。

示例代码

父类(抽象类)
abstract class Parent {
    String name;

    {
        System.out.println("Parent initialization block");
    }

    public Parent(String name) {
        this.name = name;
        System.out.println("Parent constructor called with name: " + name);
        this.init();
    }

    protected abstract void init();

    public void showName() {
        System.out.println("Name: " + name);
    }
}
子类
class Child extends Parent {
    String childName;

    {
        System.out.println("Child initialization block");
    }

    public Child(String name, String childName) {
        super(name);
        this.childName = childName;
        System.out.println("Child constructor called with childName: " + childName);
    }

    @Override
    protected void init() {
        System.out.println("Child init method called");
    }

    @Override
    public String toString() {
        return "Child{name='" + name + "', childName='" + childName + "'}";
    }
}
测试类
public class MainClass {
    public static void main(String[] args) {
        System.out.println("Main method start");
        Child child = new Child("ParentName", "ChildName");
        System.out.println("Child instance: " + child);
        child.showName();
    }
}

输出分析

运行上述代码,输出如下:

Main method start
Parent initialization block
Parent constructor called with name: ParentName
Child init method called
Child initialization block
Child constructor called with childName: ChildName
Child instance: Child{name='ParentName', childName='ChildName'}
Name: ParentName

调用顺序和输出说明

  1. 父类字段初始化和代码块

    • 父类的字段初始化和初始化块在父类构造函数之前执行。
    • 输出:“Parent initialization block”
  2. 父类构造函数

    • 父类构造函数 Parent(String name) 被调用,并打印:
      • 输出:“Parent constructor called with name: ParentName”
    • 在父类构造函数中调用 this.init() 方法,由于 init 方法在子类中被重写,因此调用的是子类的 init 方法:
      • 输出:“Child init method called”
  3. 子类字段初始化和代码块

    • 子类的字段初始化和初始化块在子类构造函数之前执行。
    • 输出:“Child initialization block”
  4. 子类构造函数

    • 子类构造函数 Child(String name, String childName) 被调用,并打印:
      • 输出:“Child constructor called with childName: ChildName”
  5. 调用 toString() 方法

    • 当打印 child 对象时,调用子类重写的 toString() 方法,返回对象的字符串表示:
      • 输出:“Child instance: Child{name=‘ParentName’, childName=‘ChildName’}”
  6. 调用 showName() 方法

    • 调用父类的方法 showName(),打印:
      • 输出:“Name: ParentName”

联系我

总结

在实例化子类时,会依次调用父类的初始化块、构造函数、以及父类构造函数中可能调用的方法。如果这些方法在子类中被重写,则会执行子类的方法。通过正确设计和调用,可以确保类在实例化时的正确初始化和方法调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值