java程序运行顺序(main方法 静态 非静态 以及衍生出的部分定义)
来源:互联网 发布:ps4适合女生的游戏知乎 编辑:程序博客网 时间:2024/06/06 17:07
Java程序运行时,第一件事情就是试图访问main方法,因为main相等于程序的入口,如果没有main方法,程序将无法启动,main方法更是占一个独立的线程。
下面是一段代码 帮助我们分析
class A { public A() { System.out.println("A的构造方法"); } public static int j = print(); public static int print() { System.out.println("A print"); return 521; }}public class Test1 extends A { public Test1() { System.out.println("Test1的构造方法"); } public static int k = print(); public static int print() { System.out.println("Test print"); return 522; } public static void main(String[] args) { System.out.println("main start"); Test1 t1 = new Test1(); }}运行结果:
A printTest printmain startA的构造方法Test1的构造方法
分析:
因为静态部分是依赖于类,而不是依赖于对象存在的,所以静态部分的加载优先于对象存在。
当找到main方法后,因为main方法虽然是一个特殊的静态方法,但是还是静态方法,此时JVM会加载main方法所在的类,试图找到类中其他静态部分,即首先会找main方法所在的类。
执行顺序大致分类:
1.静态属性,静态方法声明,静态块。
2.动态属性,普通方法声明,构造块。
3.构造方法。
1.1 静态:
当加载一个类时,JVM会根据属性的数据类型第一时间赋默认值(一举生成的)。然后再进行静态属性初始化,并为静态属性分配内存空间,静态方法的声明,静态块的加载,没有优先级之分,按出现顺序执行,静态部分仅仅加载一次。至此为止,必要的类都已经加载完毕,对象就可以被创建了。
1.2 普通:
当new一个对象时,此时会调用构造方法,但是在调用构造方法之前,(此刻1.1已经完成,除非被打断而暂停)执行动态属性定义并设置默认值(一举生成的)。然后动态属性初始化,分配内存,构造块,普通方法声明(只是加载,它不需要初始化,只有调用它时才分配内存,当方法执行完毕后内存立即释放),没有优先级之分,按出现顺序执行。最后进行构造方法中赋值。当再次创建一个对象,不再执行静态部分,仅仅重复执行普通部分。
注意:如果存在继承关系,创建对象时,依然会首先进行动态属性进行定义并设默认值,然后父类的构造器才会被调用,其他一切都是先父类再子类(因为子类的static初始化可能会依赖于父类成员能否被正确初始化),如果父类还有父类,依次类推,不管你是否打算产生一个该父类的对象,这都是自然发生的。
下面是一道阿里巴巴的面试题:非常经典,可以不断的改变程序的顺序,来找到执行顺序机制。
代码部分:
public class Text { public static int k = 0; public static Text t1 = new Text("t1"); public static Text t2 = new Text("t2"); public static int i = print("i"); public static int n = 99; public int j = print("j"); { print("构造块"); } static { print("静态块"); } public Text(String str) { System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++i; ++n; } public static int print(String str) { System.out.println((++k) + ":" + str + " i=" + i + " n=" + n); ++n; return ++i; } public static void main(String args[]) { Text t = new Text("init"); }}
运行结果:
1:j i=0 n=02:构造块 i=1 n=13:t1 i=2 n=24:j i=3 n=35:构造块 i=4 n=46:t2 i=5 n=57:i i=6 n=68:静态块 i=7 n=999:j i=8 n=10010:构造块 i=9 n=10111:init i=10 n=102
总结:只要按照这个步骤,遇到这一类问题就可以解决了。
1-3:类加载过程,不涉及构造方法
1-5: 实例化过程,涉及构造方法
1.类中所有属性的默认值(一举而成)
2. 父类静态属性初始化,静态块,静态方法的声明(按出现顺序执行)
3. 子类静态属性初始化,静态块,静态方法的声明 (按出现顺序执行)
4. 调用父类的构造方法,
首先父类的非静态成员初始化,构造块,普通方法的声明(按出现顺序执行)
然后父类构造方法
5. 调用子类的构造方法,
首先子类的非静态成员初始化,构造块,普通方法的声明(按出现顺序执行)
然后子类构造方法
(注意:类加载过程中,可能调用了实例化过程(因为static可以修饰方法,属性,代码块,内部类),此时则会暂停类加载过程而先执行实例化过程(被打断),执行结束再进行类加载过程,上面阿里那道面试题就是典型的暂停类加载。
- java程序运行顺序(main方法 静态 非静态 以及衍生出的部分定义)
- java中静态块,静态方法,非静态方法,构造方法执行的顺序
- 总结java中静态块,静态方法,非静态方法,构造方法执行的顺序
- 关于java代码中静态代码块、非静态构造代码块以及构造方法的执行顺序
- Java静态代码块、构造器、静态主方法以及继承后父类代码块的运行顺序
- 静态初始化块、非静态初始化块以及它们与构造方法的调用顺序
- 浅析java中静态方法,非静态方法和构造方法的执行顺序问题
- Java中静态变量、静态方法、静态代码块、非静态变量、非静态方法的简介(转)
- Java中静态代码块、非静态代码块以及构造函数的初始化顺序
- java 静态块 非静态块 构造方法 执行顺序
- java静态块 非静态块 构造方法顺序
- java中静态块以及方法快的加载顺序
- 方法何时定义为静态或非静态的
- Java继承中父类子类构造方法、静态代码块、非静态代码块的执行顺序
- Java中静态代码块、非静态代码块、构造方法三者的执行顺序
- Java静态初始化,非静态初始化以及构造方法
- IOS程序启动时main函数前执行的部分-load方法和静态函数
- java 静态块与非静态块的执行顺序
- python3基础知识二
- 适配小刘海OC版
- 02.类的加载
- 如何使用Jenkins的Pipeline与Jenkinsfile结合实现自动化部署
- 防止Mac程序开机自启动
- java程序运行顺序(main方法 静态 非静态 以及衍生出的部分定义)
- 欢迎使用CSDN-markdown编辑器
- Qt 类中Q_OBJECT的作用及其程序代码体现
- 欢迎使用CSDN-markdown编辑器
- VS2015 编译器报错C4996
- nginx配置说明
- Vue之axios
- 剑指offer——58.对称二叉树
- 通过自己编写的C语言程序获取lcm正常格式的初始化数据代码