zoukankan      html  css  js  c++  java
  • java“块”的研究(转)

    本文重点关注静态块、非静态块、构造函数的加载顺序

    直接上代码:

    1. package test.staticblock;  
    2. public class A {  
    3.     /*父类构造方法*/  
    4.     public A(){       
    5.         System.out.println("A constructor");  
    6.     }  
    7.       
    8.     /*父类静态块*/  
    9.     static            
    10.     {  
    11.         System.out.println("A static Block");  
    12.     }  
    13.       
    14.     /*父类非静态块*/  
    15.     {  
    16.         System.out.println("A non-static Block");  
    17.     }  
    18.       
    19.     /*父类静态方法*/  
    20.     public static void printStaticMethod(){  
    21.         System.out.println("A print Static Method");  
    22.     }  
    23.       
    24.     /*父类普通方法*/  
    25.     public void printNormalMethod(){  
    26.         System.out.println("A print Normal Method");  
    27.     }  
    28. }  
    29.   
    30. class B extends A{  
    31.     /*子类1构造方法*/  
    32.     public B(){  
    33.         System.out.println("B constructor");  
    34.     }  
    35.       
    36.     /*子类1静态块*/  
    37.     static{  
    38.         System.out.println("B static Block");  
    39.     }  
    40.       
    41.     /*子类1非静态块*/  
    42.     {  
    43.         System.out.println("B non-static Block");  
    44.     }  
    45.       
    46.     /*子类1静态方法*/  
    47.     public static void printStaticMethod(){  
    48.         System.out.println("B print Static Method");  
    49.     }  
    50.       
    51.     /*子类1普通方法*/  
    52.     public void printNormalMethod(){  
    53.         System.out.println("B print Normal Method");  
    54.     }  
    55. }  
    56.   
    57. class C extends A{  
    58.     /*子类2构造方法*/  
    59.     public C(){  
    60.         System.out.println("C constructor");  
    61.     }  
    62.       
    63.     /*子类2静态块*/  
    64.     static{  
    65.         System.out.println("C static Block");  
    66.     }  
    67.       
    68.     /*子类2非静态块*/  
    69.     {  
    70.         System.out.println("C non-static Block");  
    71.     }  
    72.       
    73.     /*子类2静态方法*/  
    74.     public static void printStaticMethod(){  
    75.         System.out.println("C print Static Method");  
    76.     }  
    77.       
    78.     /*子类2没有override父类的普通方法*/  
    79. }  
    1. package test.staticblock;  
    2.   
    3. public class Test {  
    4.     public static void main(String[] args){  
    5.         A a1 = new B();  
    6.         A a2 = new C();  
    7.           
    8.         a1.printStaticMethod();  
    9.         a1.printNormalMethod();  
    10.           
    11.         a2.printStaticMethod();  
    12.         a2.printNormalMethod();  
    13.     }  
    14. }  


    运行结果:

    1. A static Block  
    2. B static Block  
    3. A non-static Block  
    4. A constructor  
    5. B non-static Block  
    6. B constructor  
    7. C static Block  
    8. A non-static Block  
    9. A constructor  
    10. C non-static Block  
    11. C constructor  
    12. A print Static Method  
    13. B print Normal Method  
    14. A print Static Method  
    15. A print Normal Method  



    根据结果分析:

    顺序应该是这样的:父类Static->子类static->父类缺省{}->父类构造函数->子类缺省{}->子类构造函数

    A static Block

    父类静态块

    B static Block

    子类1静态块

    A non-static Block

    父类非静态块,缺省块

    A constructor

    父类构造函数

    B non-static Block

    子类1非静态块,缺省块

    B constructor

    子类1构造函数

    C static Block

    子类2静态块,由此可以看出static块仅在类加载时执行且仅执行一遍,因为A的静态块已经执行过了,这里不会再执行。

    A non-static Block

    父类非静态块,缺省块

    A constructor

    父类构造函数

    C non-static Block

    子类2非静态块,缺省块

    C constructor

    子类2构造函数

    B print Static Method

    B print Vitural Method

    C print Static Method

    A print Vitural Method


    分析:当执行new B()和new C()时,它首先去看父类里面有没有静态代码块,如果有,它先去执行父类里面静态代码块里面的内容,当父类的静态代码块里面的内容执行完毕之后,接着去执行子类(自己这个类)里 面的静态代码块,当子类的静态代码块执行完毕之后,它接着又去看父类有没有非静态代码块,如果有就执行父类的非静态代码块,父类的非静态代码块执行完毕, 接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有就执行子类的非静态代码块。子类的非静态代码块执行完毕 再去执行子类的构造方法,这个就是一个对象的初始化顺序。

    总结:对象的初始化顺序:首 先执行父类静态的内容,父类静态的内容执行完毕后,接着去执行子类的静态的内容,当子类的静态内容执行完毕之后,再去看父类有没有非静态代码块,如果有就 执行父类的非静态代码块,父类的非静态代码块执行完毕,接着执行父类的构造方法;父类的构造方法执行完毕之后,它接着去看子类有没有非静态代码块,如果有 就执行子类的非静态代码块。子类的非静态代码块执行完毕再去执行子类的构造方法。总之一句话,静态代码块内容先执行,接着执行父类非静态代码块和构造方 法,然后执行子类非静态代码块和构造方法。

    注意:子类的构造方法,不管这个构造方法带不带参数,默认的它都会先去寻找父类的不带参数的构造方法。如果父类没有不带参数的构造方法,那么子类必须用supper关键子来调用父类带参数的构造方法,否则编译不能通过。


    重要一点:

    static 块仅在类加载时,并非实例化时,被执行一遍,且在整个过程中只可能被执行一遍,这也就是在实例化C时

    A a2 = new C();

    A的static块没有被执行的原因。

    但非静态块在实例化对象时总会被执行。

     

    静态块一般用于初始化类中的静态成员;而非静态块一般用于初始化类中的非静态成员;

    另外,非静态块是在创建对象时自动执行的代码。


    部分参考:

    http://blog.sina.com.cn/s/blog_499b09000100d9rj.html

  • 相关阅读:
    chapter4.6生成器
    chapter4.4、递归
    chapter4.3、函数执行流程
    chapter4.2、函数返回值
    直接插入排序
    打印三角型的练习
    杂记
    linux top命令
    makefile 中的 := , += ,?=
    makefile中的shell语法 || Makefile中的@
  • 原文地址:https://www.cnblogs.com/end/p/2827549.html
Copyright © 2011-2022 走看看