Java代码的执行顺序,静态代码块、静态成员变量的执行顺序,有父子类的继承时的执行顺序(代码图文演示)

本文详细解释了Java代码中静态代码块、静态成员变量、非静态代码块及构造方法的执行顺序,包括没有父子类和有父子类情况下的执行逻辑。

Java代码的执行顺序

也就是一个类中有很多部分的代码,它们的执行顺序是怎样的?

一、没有父子级时的执行顺序

1、 静态代码块 和 main 方法:先执行 静态代码块,与位置无关

2、 假如类中定义 静态成员变量(该变量是个对象,普通的成员变量也适用),那么会先创建对象:

假如 2 的代码块在 1 的前面写,则先执行 2,是由位置决定的。而 main 始终在 1,2 最后,跟位置没有关系。

3、 需注意:

① 如果是非静态代码块、非静态成员变量(该变量是个对象),是不会执行的:

② 这个时候,只有在创建 Test 对象的时候(也就是它们所在类的对象),才会执行 非静态代码块、非静态成员变量(该变量是个对象):此时 三者的执行的顺序 是按照位置的先后。

4、 如果同时存在 非静态代码块、静态代码块、非静态成员变量(对象)、静态成员变量(对象):

先执行静态的东西,并且只执行一次;再执行非静态的东西(能执行的前提:先创建对象),创建多少个就执行多少次。

二、有父子级时的执行顺序

有资源类 Res、父类 Parent、子类 Children,测试类 Test。代码分别如下,那执行顺序是怎样的?

public class Res {
    public Res(String str){
        System.out.println(str + "方式:调用 Res 的构造方法,创建 Res 资源。");
    }
}           
public class Parent {

    static Res parentRes = new Res("父类的静态成员变量,该变量(是父类创建 Res 对象)");

    static {
        System.out.println("父类的静态代码块");
    }

    {
        System.out.println("父类的非静态代码块");
    }

    Res parentRes1 = new Res("父类的非静态成员变量,该变量(是父类创建 Res 对象)");

    Res parentRes2;

    public Parent(){
        System.out.println("父类的无参构造");
        parentRes2 = new Res("在父类的无参构造中创建 Res 对象");
    }

    public void sayHello(){
        System.out.println("父类的普通方法");
    }
}
public class Children extends Parent{

    static Res childrenRes = new Res("子类的静态成员变量,该变量(是子类创建 Res 对象)");

    static {
        System.out.println("子类的静态代码块");
    }

    {
        System.out.println("子类的非静态代码块");
    }

    Res childrenRes1 = new Res("父类的非静态成员变量,该变量(是子类创建 Res 对象)");

    Res childrenRes2;

    public Children(){
        System.out.println("子类的无参构造");
        childrenRes2 = new Res("在子类的无参构造中创建 Res 对象");
    }

    public void sayHello(){
        System.out.println("子类的普通方法");
    }
}
public class Test {
    public static void main(String[] args) {
        Children children = new Children();
        children.sayHello();
        System.out.println("*******");
        //子类强转父类后,再调方法
        ((Parent) children).sayHello();
    }
}

运行结果:

父类的静态成员变量,该变量(是父类创建 Res 对象),方式:调用 Res 的构造方法,创建 Res 对象。
父类的静态代码块
子类的静态成员变量,该变量(是子类创建 Res 对象),方式:调用 Res 的构造方法,创建 Res 对象。
子类的静态代码块
父类的非静态代码块
父类的非静态成员变量,该变量(是父类创建 Res 对象),方式:调用 Res 的构造方法,创建 Res 对象。
父类的无参构造
在父类的无参构造中创建 Res 对象,方式:调用 Res 的构造方法,创建Res 对象。
子类的非静态代码块
子类的非静态成员变量,该变量(是子类创建 Res 对象),方式:调用 Res 的构造方法,创建 Res 对象。
子类的无参构造
在子类的无参构造中创建 Res 对象,方式:调用 Res 的构造方法,创建Res 对象。
子类的普通方法
在这里插入图片描述
子类的普通方法

分析:

① 首先代码从 main 方法入口开始

Children children = new Children(); 创建子类对象、会调子类的构造器,子类构造器的首行默认会有 super() 方法,所以会 优先调父类的无参构造,所以会先加载 Parent 类,其中 静态代码块 和 静态成员变量 会优先执行,即输出前 2 行:

父类的静态成员变量,该变量(是父类创建 Res 对象),方式:调用 Res 的构造方法,创建 Res 对象。
父类的静态代码块

③ Parent 类加载完后,再去加载 Children 类,因为 先加载类再执行,所以输出第3、4行:

子类的静态成员变量,该变量(是子类创建 Res 对象),方式:调用 Res 的构造方法,创建 Res 对象。
子类的静态代码块

④ 类都加载完后,就开始创建对象,默认会先创建父类对象,但调构造器之前会先执行类中的 非静态东西,然后再开始通过父类自己的无参构造创建父类对象,所以输出第5、6、7、8行:

父类的东西都搞完后,再开始搞子类的东西,同理,输出9、10、11、12行:

创建对象完后,对象开始执行方法children.sayHello();,输出13、14行:

⑦ 虽然进行了强制类型转换,但对象还是来自内存中的子类对象。

Java中,**静态代码块(Static Block)** 是的一部分,用于初始化静态成员执行一些仅需一次的初始化操作。其执行顺序加载机制密切相关,并遵循特定规则。 ### 静态代码块的基本特性 - **只执行一次**:无论创建多少个实例对象,静态代码块仅在第一次被加载执行一次。 - **按定义顺序执行**:如果一个中有多个静态代码块,它们将按照在源码中出现的顺序依次执行。 - **优先于构造方法和实例代码块执行**:静态代码块加载运行,早于实例化过程中的构造方法和实例代码块。 ### 继承关系下的执行顺序 当涉及继承结构静态代码块执行顺序如下: 1. **父静态代码块** 先于子静态代码块执行; 2. 然后是 **子静态代码块**; 3. 接着是 **父的实例代码块** 和 **父构造方法**; 4. 最后是 **子的实例代码块** 和 **子构造方法**。 示例代码演示了这一顺序: ```java class TestTwo { static { System.out.println("父静态代码块"); } { System.out.println("父代码块"); } public TestTwo() { System.out.println("父构造方法"); } } public class testOne extends TestTwo { static { System.out.println("子静态代码块"); } { System.out.println("子代码块"); } public testOne() { System.out.println("子构造方法"); } public static void main(String[] args) { new testOne(); } } ``` 运行结果为: ``` 父静态代码块静态代码块代码块构造方法 子代码块构造方法 ``` ### 静态属性初始化与静态代码块的关系 静态属性的初始化也发生在加载阶段,且**静态属性初始化先于静态代码块执行**,但多个静态属性之间仍按照其在代码中的声明顺序进行初始化[^4]。 例如: ```java class A { private static int n1 = getVal1(); static { System.out.println("A的一个静态代码块"); } public static int getVal1() { System.out.println("A的静态属性"); return 0; } } ``` 执行输出顺序为: ``` A的静态属性 A的一个静态代码块 ``` ### 总结执行顺序 1. 父静态属性初始化 → 父静态代码块; 2. 子静态属性初始化 → 子静态代码块; 3. 父静态属性初始化 → 父实例代码块 → 父构造方法; 4. 子静态属性初始化 → 子实例代码块 → 子构造方法。 该机制确保了静态部分在实例化之前完成初始化,同也保证了父子之间的初始化顺序正确。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小学鸡!

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

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

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

打赏作者

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

抵扣说明:

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

余额充值