Java程序执行流程分析

时间:2021-12-14 17:06:54

刚刚在复习JavaSE, 正好复习到 程序执行流程,所以写下这篇博客记录下
问题:一下这段代码的执行顺序

public class Test {
private String name="Jack";
private int age=2;
public Test( ) {
age=1000; //期望能到1000年
}
public static void main(String [] args ) {
Test t = new Test();
System.out.println(t.name + " " + t.age);
}
}

还是用图片好一点
Java程序执行流程分析

我看到第一眼的答案是 先是main函数入口,第七行,再就是 第八行,再就是 第四行 然后 就第五行 再就是 第六行。 接下来我就发现我做不下去。
后来看了笔记想了想才知道我错了 。
main函数入口第七行开始这个肯定不会错,在往下走,第八行 这个时候new Test(); 调用了方法, 应该是直接去找方法 所以是第四行 也没错。接下来 往下 构造方法这里省略了一句 super();调用父类构造方法。当然这里父类是object 所以当做没有。 接下来呢 就是构造方法的特殊性了。 既然是构造方法 当然是要构造这个类啊, 就是要加载这个类的信息了,初始化一个类,必须先初始化它的属性 从第四行开始后, 就调到第二行加载这个类的属性 (至于为什么不是第一行而是第二行我也没想清楚,可能是因为第二行开始才是类的属性信息吧)再一直往下 第三行 直到把所有的这个类的属性加载完,在执行第五行,接着第六行。第六行执行完了以后才真正代表第八行执行完了,接下来就是第九行 一直到末尾
所以答案是 7 8 4 2 3 5 6 9 10 11

第二个例子: 是如下三段代码。 执行man函数输出什么结果
Java程序执行流程分析

package com.obj;

public class Test2 {

public String s = "11111";
{
System.out.println("Test的属性");
}
public Test2(){
System.out.println("Test的构造方法");
}
}
package com.obj;

public class T1 extends Test2{
{
System.out.println("T1的属性");
}
public T1(){
super();
System.out.println("T1的构造方法");
}
}
package com.obj;

public class T2 extends T1{
{
System.out.println("T2的属性");
}
public T2(){
super();
System.out.println("T2的构造方法");
}
public static void main(String[] args) {
T2 t = new T2();

}

}

我不代码的执行步骤用换图的方式表示出来了
Java程序执行流程分析
第一步:Java虚拟机肯定main函数入口的
第二步:main函数里面往下走, 调用T2的构造方法。
第三步:T2的构造方法,构造方法会调用父类T1的构造的方法super();
就到了T1的构造方法,T1的构造方法又super().T1的父类Test的构造方法
第四步:调用Test的构造方法,当然要调用super(); 就是object, 当做没有吧,之后就加载Test的属性
第五步:Test的属性加载
第六步:Test的属性加载
第七步:Test的属性加载完毕,Test构造方法完成。
第八步:Test这边完成就等于 T1构造方法中的super()完成,就下来就是加载T1的属性
第九步:T1的属性加载完成,就是继续完成自己的构造方法。
第十步:T1加载完成,也就是T2的构造方法中super()方法完成,就下来就是记载T2的属性
第十一步:完成自己的构造方法。

因此输出的信息为:
Test的属性
Test的构造方法
T1的属性
T1的构造方法
T2的属性
T2的构造方法

小小的总结:
程序加载第一步虚拟机肯定会找main函数 如果调用构造方法,那么构造方法 会先 加载父类的构造方法,再加载自己的属性。

看第三个例子

public class Test2{
static int i=5;
public static void main(String[] args){
Father father = new Child();
father = new Child();
System.out.println( (change()==3)?i+15:i+10.0 );
}
public static int change(){
if(i==5){
i = i+10;
}
return i = i/5;
}
}
class Father{
public Father(){
System.out.println("father...");
}
static{
System.out.println("father2");
}
}
class Child extends Father{
public Child(){
System.out.println("child...");
}
static{
System.out.println("child2");
}
}

结果是:
father2
child2
father…
child…
father…
child…
18.0

我的理解是 把static内容分开,因为static是静态的 和非static内容不用,static可以看成一个 模具,非static 的内容都是根据static 复制出来的。所以相对于 “产品” 必须先有模具 而且模具 只有一套就够了。 因此statc的内容是最先输出来的。 而且是先父类再子类。 因为没有父类 子类的信息哪儿来? 怎么加载? 其他的就前面的类似了。。