• 由阿里巴巴一道笔试题看Java静态代码块、静态函数、动态代码块、构造函数等的执行顺序


    一、阿里巴巴笔试题:

    [java] view plaincopy
     
     
    1. public class Test {  
    2.     public static int k = 0;  
    3.     public static Test t1 = new Test("t1");  
    4.     public static Test t2 = new Test("t2");  
    5.     public static int i = print("i");  
    6.     public static int n = 99;  
    7.     private int a = 0;  
    8.     public int j = print("j");  
    9.       
    10.     {  
    11.         print("构造块");  
    12.     }  
    13.   
    14.     static {  
    15.         print("静态块");  
    16.     }  
    17.   
    18.     public Test(String str) {  
    19.         System.out.println((++k) + ":" + str + "    i=" + i + "     n=" + n);  
    20.         ++i;  
    21.         ++n;  
    22.     }  
    23.   
    24.     public static int print(String str) {  
    25.         System.out.println((++k) + ":" + str + "    i=" + i + "     n=" + n);  
    26.         ++n;  
    27.         return ++i;  
    28.     }  
    29.   
    30.     public static void main(String args[]) {  
    31.         Test t = new Test("init");  
    32.     }  
    33. }  


    输出:

    [plain] view plaincopy
     
     
    1. 1:j    i=0     n=0  
    2. 2:构造块    i=1     n=1  
    3. 3:t1    i=2     n=2  
    4. 4:j    i=3     n=3  
    5. 5:构造块    i=4     n=4  
    6. 6:t2    i=5     n=5  
    7. 7:i    i=6     n=6  
    8. 8:静态块    i=7     n=99  
    9. 9:j    i=8     n=100  
    10. 10:构造块    i=9     n=101  
    11. 11:init    i=10     n=102  

    二、我们暂且先不看这道题,先回忆一下代码块、构造函数执行顺序的基本知识:

    总体规则:静态代码块 -> 动态代码块 ->构造函数

    静态代码块只在第一次new的时候执行一次,之后不再执行;动态代码块在每次new的时候都执行一次。

    在不涉及继承的情况下:

    1.静态代码块和静态成员变量在加载代码时执行,只执行一次,按照它们出现的顺序先后执行;

    2.动态代码块在每次实例化对象时执行,在构造函数之前执行,多个动态代码块按照它们出现的顺序先后执行;

    在涉及继承的情况下:

    1.执行父类的静态代码块和静态成员变量定义,执行子类的静态代码块和静态成员变量定义;

    2.执行父类的动态代码块,执行父类的构造函数;

    3.执行子类的动态代码块,执行子类的构造函数;

    4.如果父类构造函数中用到的函数被子类重写,那么在构造子类对象时调用子类重写的方法;

    代码:

    [java] view plaincopy
     
     
    1. public class staticTest {  
    2.     public static void main(String[] args) {  
    3.         A a1 = new B();  
    4.     }  
    5. }  
    6.   
    7. class A{  
    8.     public A(){  
    9.         System.out.println("A constructor.");  
    10.         func();  
    11.     }  
    12.       
    13.     static{  
    14.         System.out.println("class A static block.");  
    15.     }  
    16.       
    17.     private int ai = getAi();  
    18.   
    19.     {  
    20.         System.out.println("class A dynamic block.");  
    21.     }  
    22.       
    23.     private static int asi = getAsi();  
    24.       
    25.     private int getAi(){  
    26.         System.out.println("class A dynamic int.");  
    27.         return 1;  
    28.     }  
    29.       
    30.     private static int getAsi(){  
    31.         System.out.println("class A static int.");  
    32.         return 0;  
    33.     }  
    34.       
    35.     public void func(){  
    36.         System.out.println("A.func()");  
    37.     }  
    38. }  
    39.   
    40.   
    41. class B extends A{  
    42.     public B(){  
    43.         System.out.println("B constructor.");  
    44.         func();  
    45.     }  
    46.       
    47.     static{  
    48.         System.out.println("class B static block.");  
    49.     }  
    50.       
    51.     private int bi = getBi();  
    52.       
    53.     {  
    54.         System.out.println("class B dynamic block.");  
    55.     }  
    56.       
    57.     private static int bsi = getBsi();  
    58.       
    59.     private int getBi(){  
    60.         System.out.println("class B dynamic int.");  
    61.         return 1;  
    62.     }  
    63.       
    64.     private static int getBsi(){  
    65.         System.out.println("class B static int.");  
    66.         return 0;  
    67.     }  
    68.       
    69.     public void func(){  
    70.         System.out.println("B.func()");  
    71.     }  
    72. }  


    输出:

    [plain] view plaincopy
     
     
    1. class A static block.  
    2. class A static int.  
    3. class B static block.  
    4. class B static int.  
    5. class A dynamic int.  
    6. class A dynamic block.  
    7. A constructor.  
    8. B.func()  
    9. class B dynamic int.  
    10. class B dynamic block.  
    11. B constructor.  
    12. B.func()  


    三、对阿里巴巴笔试题的分析

    [java] view plaincopy
     
     
    1. public static int k = 0;  
    2. public static Test t1 = new Test("t1");  


    函数先执行到这里,在构造t1的过程中发生了什么呢,通过对程序打断点分析,我发现,程序并没有执行其中的静态代码块,而是执行非静态代码块,为什么呢?我的理解是,“静态代码块只在程序加载的时候运行,并且是按其出现顺序加载的”,而现在我们在构造一个新对象,属于程序加载的时候的一个分支,然后还会走回来继续加载剩下的未加载的静态代码块。所以在这次创建静态对象的过程中,之后执行其中的非静态代码块。

    下面我们看到的两个*****中间的就是在执行该语句的过程中产生的分支:

    **********

    所以接下来执行的是:

    [java] view plaincopy
     
     
    1. private int a = 0;  
    2. public int j = print("j");  

    执行第二句的时候会调用

    [java] view plaincopy
     
     
    1. public static int print(String str) {  
    2.     System.out.println((++k) + ":" + str + "    i=" + i + "     n=" + n);  
    3.     ++n;  
    4.     return ++i;  
    5. }  


    然后执行动态代码块:

    [java] view plaincopy
     
     
    1. {  
    2.     print("构造块");  
    3. }  


    然后调用构造函数:

    [java] view plaincopy
     
     
    1. public Test(String str) {  
    2.     System.out.println((++k) + ":" + str + "    i=" + i + "     n=" + n);  
    3.     ++i;  
    4.     ++n;  
    5. }  


    这个顺序就是“动态代码块->构造函数"。

    *************

    然后跳出该分支,继续加载静态代码块:

    [java] view plaincopy
     
     
    1. public static Test t2 = new Test("t2");  


    执行此句会重复上面两个********之间的分支,这里不再赘述。

    然后是:

    [java] view plaincopy
     
     
    1. public static int i = print("i");  
    2. public static int n = 99;  
    3.   
    4. static {  
    5.     print("静态块");  
    6. }  


    最后执行main函数里面的部分,依次调用动态代码块和构造函数,不再赘述。

  • 相关阅读:
    HTML
    JavaScript事件对象
    JavaScript 事件入门
    如何向github上传文件
    crystal
    BUUCTF[强网杯 2019]随便注wp
    BUUCTF[CISCN2019 华东南赛区]Web4 wp
    BUUCTF[NPUCTF2020]ezinclude wp
    Windows下Ant的环境配置
    Java解惑(1)——表达式之谜
  • 原文地址:https://www.cnblogs.com/hxj914103719/p/4372037.html
Copyright © 2020-2023  润新知