【Java】new运算执行顺序问题

作者:Leopold    访问量:4

new运算执行顺序问题

1 继承

1.1 父类实例化父类

  • 父类 App
package com.tyq;

public class App {
    static {
        System.out.print(1);
    }
    
    {
        System.out.print(3);
    }
    
    public App() {
        System.out.print(5);
    }

    static {
        System.out.print(2);
    }

    {
        System.out.print(4);
    }
}
  • 子类 Tim
package com.tyq;

public class Tim extends App {
    static {
        System.out.print("A");
    }

    static {
        System.out.print("B");
    }

    {
        System.out.print("C");
    }

    {
        System.out.print("D");
    }

    public Tim() {
        System.out.print("E");
    }
}

  • 测试类 Sys
package com.tyq;

public class Sys {
    public static void main(String[] args) {
        App a = new App();
        System.out.println();
        Tim b = new Tim();
    }
}

  • 结果:
12345

执行顺序总结:

静态代码块 > 代码块 > 构造函数

由此可知,即便代码块在前,静态代码块在后,都以上面执行顺序为主。

1.2 子类实例化子类

  • 测试类 Sys
package com.tyq;

public class Sys {
    public static void main(String[] args) {
        Tim b = new Tim();
    }
}

  • 结果:
12AB345CDE

执行顺序总结:

子类静态代码块 > 父类代码块 > 父类构造函数 > 子类代码块 > 子类构造函数

1.3 父类实例化子类(强制类型转换)

  • 测试类Sys
package com.tyq;

public class Sys {
    public static void main(String[] args) {
        App a = new Tim();
    }
}
  • 测试结果
12AB345CDE

执行顺序总结:

父类静态代码块 > 子类静态代码块 > 父类代码块 > 父类构造方法 > 子类代码块 > 子类构造方法

1.4 分析

1.4.1 编译期和运行期

首先要区分,什么是Java的编译期、运行期?

  • 编译期:是指把源码交给编译器编译成计算机可以执行的文件的过程。在Java中也就是把.java编成.class文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误。
  • 运行期:是把编译后的文件交给计算机执行,直到程序运行结束。所谓运行期就把在磁盘中的代码放到内存中执行起来,在Java中把磁盘中的代码放到内存中就是类加载过程,类加载是运行期的开始部分。

在编译期过程中,首先进行词法分析,其次是语法分析,然后是语义分析,最后代码生成器生成代码

在运行期过程中,

​ 1)首先将.class字节码文件(二进制数据)加载到内存中,并放入方法区中。其次是在堆区创建一个java.lang.Class对象,用来封装类在方法区内的数据结构。

​ 2)紧接着,Java虚拟机对类的静态变量分配内存,并设置初始值(e.g. static int a =0;)。

​ 3)然后,Java虚拟机执行类的初始化语句,为类的静态变量赋值,这里包含实例域中,静态变量的声明,以及静态代码块中的声明

​ 4)程序开始运行,比如执行Sys类中的main函数。

由此可知,在实例化对象中,一定是先执行的静态代码块,但是,静态代码块在类初始化时,仅执行一次,比如以下的这个例子。

package com.tyq;

public class Sys {
    public static void main(String[] args) {
        App a = new App();
        System.out.println();
        Tim b = new Tim();
    }
}

执行结果为:

12345
AB345CDE

这里实例化Tim类时,父类App的静态代码块便不再运行。

1.4.2 继承中的先后顺序

子类在实例化过程中,如果子类的构造器没有显式地调用父类的构造器,则将自动地调用父类默认(没有参数)的构造器



如果您觉得此文章对您有帮助,欢迎评论转载!

您的每一次评论与转载,都是对作者极大的鼓励!

注意:除非注明,否则均为[Leopold's Blog]原创文章,转载必须以链接形式标明本文链接。

本文链接:https://www.yusong.site/leopold/779.html

发表评论

电子邮件地址不会被公开。 必填项已用*标注