OOP 多态和构造器执行顺序

本文详细解析了Java中对象初始化顺序与多态性的概念,包括静态成员、构造器及继承链中的构造调用顺序等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OOP 多态和构造器执行顺序


在java的面试题中,对象的初始化顺序配合多态是一种常见考题!今天我就来详细的回顾一下!

类中一般包括这几个部分:

  • 静态成员 包括静态的成员变量 静态代码块、
  • 非静态的成员变量
  • 构造函数 (其实也是一种静态方法,只不过static是隐式的)
  • 静态方法和非静态方法

Java尽力保证,所有变量在使用前都能得到恰当的初始化

方法的局部变量 java以编译时错误的形式来贯彻这种保证;而对于类的成员变量,如果是基本数据类型都保证会有一个默认值,如果是引用类型,未被初始化则会被赋值为Null!

静态成员—–>成员变量(相互之间按照定义顺序)—–>构造器等任何方法

初始化对象时,并不会执行静态方法。静态方法直接通过类名进行访问


对象的创建过程

以Dog类为例

1.即使没有显示的指定static关键字,构造器实际上也是静态方法。因此,当首次创建类型为Dog的对象(构造器可以看成静态方法),或者Dog的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位Dog.class文件

2.然后载入Dog.class,有关静态初始化的所有动作(静态成员变量 静态代码块)都会执行。因此,静态初始化只在class对象首次加载的时候进行一次

3.当用new Dog()创建对象的时候,首先在堆上为Dog对象分配足够的存储空间

4.这块存储空间将会被清零,这就自动的将Dog对象中的所有基本数据类型都设置为默认值,而引用则被设置为null

5.执行父类的构造函数,依次递归直到继承层级的根。首先执行根,然后是下一层导出类,直到最近父类

5.执行所有出现于成员变量定义处的初始化操作

6.执行构造器本体


构造器与多态

基类的构造器总是在导出类的构造过程中被调用,并且按照集成的层次逐渐向上链接,以使每个基类的构造器都得以调用!

对复杂对象调用构造器的顺序:

1.首先调用基类的构造器。这个步骤会反复递归下去,首先是构造这种层次结构的,然后是下一层的导出类,等等知道最底层的导出类,也就是最近父类

2.按照声明顺序调用成员的初始化方法

3.调用导出类构造器的本体


例子

  • SomeThing.java
package OOP;

public class SomeThing {
    public SomeThing() {
        System.out.println("SomeThing 构造方法正在执行");
    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • Person.java
package OOP;

public class Person extends SomeThing {
    static{
        System.out.println("Person 静态代码块正在执行");
    }
    public Person() {
        System.out.println("Person 构造方法正在执行");
    }
    public void introduce(){
        System.out.println("你好,我是一个Person");
    }
    //此方法只有Person有,未被覆盖
    public void personShow(){
        System.out.println("Welcome to Person's Show");
    }
    //静态方法
    public static void SoLo(){
        System.out.println("Person静态方法正在执行");
    }


}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • Student.java
package OOP;

public class Student extends Person {
    //成员变量,声明处实例化
    private StudentInfo info = new StudentInfo();
    static {
        System.out.println("Student 静态代码块正在执行");
    }

    public Student() {
        System.out.println("Student 构造方法正在执行");
    }

    // 覆盖的方法
    public void introduce() {
        System.out.println("你好,我是一个Student");
    }

    public void studentShow() {
        System.out.println("Welcome to Student's Show");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • StudentInfo.java
package OOP;

public class StudentInfo {
    public StudentInfo() {
        System.out.println("正在执行 StudentInfo 构造器");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • OOPdemo.java
package OOP;

public class OOPdemo {

    public static void main(String[] args) {
        //1.首先声明对象为Person类型,则Person中静态成员会被执行
        //2.然后调用Student的构造函数,加载Student类,静态成员先执行
        //3.调用Student的构造函数,默认先调用父类的构造函数,递归直到根
        //4.调用Student的构造函数,先初始化Student的成员变量,基本类型赋默认值,
        //引用类型未初始化赋值为NULL,有初始化操作则执行
        //5.调用Student构造函数的本体
        Person p=new Student();
        System.out.println("p的类型---"+p);
        //执行覆盖方法,执行子对象(实际对象)
        p.introduce();
        //执行父类方法,未覆盖
        p.personShow();;

        //因为是Person引用所以,student类中添加的方法,person对象不可见
        //没有 p.studentShow()
        ((Student)p).studentShow();





    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 执行结果

这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值