刚刚在复习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执行指定入口 java程序执行的入口方法_Test

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

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

java执行指定入口 java程序执行的入口方法_加载_02

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程序执行的入口方法_Test_03


第一步: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的内容是最先输出来的。 而且是先父类再子类。 因为没有父类 子类的信息哪儿来? 怎么加载? 其他的就前面的类似了。。