zoukankan      html  css  js  c++  java
  • java中普通变量、静态变量、静态代码块初始化的顺序辨析

    1.普通变量的初始化

    看如下程序

    1. class Window{  
    2.     public Window(int maker) {  
    3.         System.out.println("Window("+maker+")");  
    4.     }  
    5. }  
    6.   
    7. class House{  
    8.     Window w1 = new Window(1);  
    9.     public House() {  
    10.         System.out.println("House()");  
    11.         w3 = new Window(33);  
    12.     }  
    13.     Window w2 = new Window(2);  
    14.     void f(){  
    15.         System.out.println("f()");  
    16.     }  
    17.     Window w3 = new Window(3);  
    18.       
    19. }  
    20.   
    21. public class Test {  
    22.       
    23.     public static void main(String[] args) {  
    24.         House h = new House();  
    25.         h.f();  
    26.     }  
    27. }  
    28. /*  
    29.   结果如下:  
    30. Window(1)  
    31. Window(2)  
    32. Window(3)  
    33. House()  
    34. Window(33)  
    35. f()  
    36. */  

    分析:普通变量在类中的任何方法(包括构造函数)之前初始化(规则一)。

     

    2.静态变量的初始化

    1. class Bowl{  
    2.     public Bowl(int maker) {  
    3.         System.out.println("Bowl("+maker+")");  
    4.     }  
    5.     void f1(int maker){  
    6.         System.out.println("f1("+maker+")");  
    7.     }  
    8. }  
    9.   
    10. class Table{  
    11.     static Bowl bowl1 = new Bowl(1);  
    12.     static Bowl bowl2 = new Bowl(2);  
    13.       
    14.     public Table() {  
    15.         System.out.println("Table()");  
    16.         bowl2.f1(1);  
    17.     }  
    18.     void f2(int maker){  
    19.         System.out.println("f2("+maker+")");  
    20.     }  
    21. }  
    22.   
    23. class Cupboard{  
    24.     Bowl bowl3 = new Bowl(3);  
    25.     static Bowl bowl4 = new Bowl(4);  
    26.     static Bowl bowl5 = new Bowl(5);  
    27.       
    28.     public Cupboard() {  
    29.         System.out.println("cupboard()");  
    30.         bowl4.f1(2);  
    31.     }  
    32.     void f3(int maker){  
    33.         System.out.println("f3("+maker+")");  
    34.     }  
    35. }  
    36.   
    37. public class Test {  
    38.       
    39.     static Table table = new Table();  
    40.     static Cupboard cupboard = new Cupboard();  
    41.       
    42.     public static void main(String[] args) {  
    43.         System.out.println("creating new cupboard() in main");  
    44.         new Cupboard();  
    45.         System.out.println("creating new cupboard() in main");  
    46.         new Cupboard();  
    47.         table.f2(1);  
    48.         cupboard.f3(1);  
    49.           
    50.     }  
    51. }  
    52. /*  
    53.   结果如下:  
    54. Bowl(1)  
    55. Bowl(2)  
    56. Table()  
    57. f1(1)  
    58. Bowl(4)  
    59. Bowl(5)  
    60. Bowl(3)  
    61. cupboard()  
    62. f1(2)  
    63. creating new cupboard() in main  
    64. Bowl(3)  
    65. cupboard()  
    66. f1(2)  
    67. creating new cupboard() in main  
    68. Bowl(3)  
    69. cupboard()  
    70. f1(2)  
    71. f2(1)  
    72. f3(1)  
    73.   
    74. */<span style="color:#ff0000">  
    75. </span>  

    分析:

    1.首先程序总共有4个类(Bowl,Table,Cupboard,Test),Bowl没有静态变量和静态方法;Table中有静态变量bowl1、bowl2;Cupboard中有普通变量bowl3,静态变量bowl4、bowl5;Test中有静态变量table、cupboard。

    2.根据规则:使用static命名的变量或者使用static{}包括起来的区域,都在类被加载时进行初始化(规则二)。

    3.虚拟机首先加载Test,需要初始化table变量,加载Table类。Table类中有静态变量bowl1,bowl2,初始化它们,输出"Bowl(1),Bowl(2)",再调用构造函数来new对象,输出"Table(),f1(1)"。然后加载Cupboard类,初始化静态变量bowl4,bowl5,输出"Bowl(4),Bowl(5)",调用构造函数来new对象,首先初始化普通变量bowl3,输出"Bowl(3)",然后构造函数,输出"cupboard(),f1(2)"。

    4.执行main方法,先输出"creating new cupboard() in main",执行new Cupboard(),这时静态变量都初始化了,不必继续初始化。初始化一般变量bowl3,输出"bowl3",然后调用构造函数,输出"cupboard(),f1(2)"。在输出"creating new cupboard() in main",同理输出"bowl3,cupboard(),f1(2)",最后继续执行main函数,输出"f2(1),f3(1)"。

     

    3.静态代码块的初始化

    1. class Spoon{  
    2.       
    3.     public Spoon(int maker) {  
    4.         System.out.println("Spoon("+maker+")");  
    5.     }  
    6.     static int i;  
    7.     static Spoon s = new Spoon(1);  
    8.     static{  
    9.         System.out.println("static code ");  
    10.         i = 47;  
    11.     }     
    12. }  
    13.   
    14. public class Test {  
    15.     public static void main(String[] args) {  
    16.         new Spoon(2);  
    17.     }  
    18. }  
    19. /*  
    20. Spoon(1)  
    21. static code   
    22. Spoon(2)  
    23. */  
    24. /*  
    25.  如果写成  
    26.     static{  
    27.         System.out.println("static code ");  
    28.         i = 47;  
    29.     }  
    30.     static Spoon s = new Spoon(1);  
    31. 结果为:  
    32. static code   
    33. Spoon(1)  
    34. Spoon(2)  
    35.   */  


    分析:静态代码块跟静态变量都是类加载时进行初始化的(同等条件下,初始化顺序由书写顺序决定)

     

    4.非静态代码块

    1. class Spoon{  
    2.       
    3.     public Spoon(int maker) {  
    4.         System.out.println("Spoon("+maker+")");  
    5.     }  
    6.     static int i;  
    7.       
    8.     static Spoon s = new Spoon(1);  
    9.     static{  
    10.         System.out.println("static code ");  
    11.         i = 47;  
    12.     }  
    13.       
    14.       
    15.     int a;  
    16.     //非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中  
    17.     {  
    18.         System.out.println("non-static instatnce");  
    19.         a = 1;  
    20.     }  
    21. }  
    22.   
    23.   
    24. public class Test {  
    25.     public static void main(String[] args) {  
    26.         new Spoon(2);  
    27.         new Spoon(3);  
    28.     }  
    29. }  
    30. /*  
    31. non-static instatnce  
    32. Spoon(1)  
    33. static code   
    34. non-static instatnce  
    35. Spoon(2)  
    36. non-static instatnce  
    37. Spoon(3)  
    38.   */  


    分析:

    1.main函数执行new Spoon(2)语句,首先加载Spoon类,先初始化静态变量s,s调用new Spoon(1),此时类Spoon已经加载,所以不用管静态变量和静态代码块了,然后调用非静态代码块和构造函数,输出"non-static code,spoon(1)"。

    2.初始化静态代码块,输出"static code"。

    3.执行new spoon(2)语句输出“non-static instatnce,Spoon(2)“。

    4.执行"new spoon(3)"语句输出”non-static instatnce,Spoon(3)”。

    可以尝试调换静态变量s和静态代码块的顺序,发现只是1和2的先后顺序改变而已。

     

    在看下面这个程序

    1. <span style="font-size:18px">class T{  
    2.     public T() {  
    3.         System.out.println("T constructor");  
    4.     }  
    5. }  
    6. class Spoon{  
    7.       
    8.     public Spoon(int maker) {  
    9.         System.out.println("Spoon("+maker+")");  
    10.     }  
    11.     int a;  
    12.     //非静态代码块与直接为变量赋值效果相同,只不过可以写更为复杂的代码,非静态代码块一般用于内部类中  
    13.     {  
    14.         System.out.println("non-static instatnce");  
    15.         a = 1;  
    16.     }  
    17.     T t1 = new T();  
    18. }  
    19.   
    20. public class Test {  
    21.     public static void main(String[] args) {  
    22.         new Spoon(2);  
    23.     }  
    24. }  
    25. /* 
    26. non-static instatnce 
    27. T constructor 
    28. Spoon(2) 
    29.  
    30.   */  
    31. </span>  

    通过这个程序,可以发现非静态变量和非静态代码块顺序由书写顺序决定

    5.总结:

      以Dog类为例

      1.当第一次执行到需要使用Dog类时(如Dog d = new Dog),java首先通过寻找classpath来找到Dog.class,进行加载.

      2.初始化Dog类的静态变量和静态代码块(按书写顺序,若静态变量或代码块中还有new Dog,此时不用再管静态变   量和代码块了,如第五个程序中的"static Spoon s = new Spoon(1)")。

      3.系统给类分配足够大的内存空间,初始化非静态变量和非静态代码块(顺序由书写顺序决定)

      4.最后执行Dog类的构造函数。

      5.以后如果还要new Dog类对象时(不是第一次使用了),重复3和4的步骤,不会再去初始化静态变量和静态代码     块了。

       大家可以自己写程序实验一下。

     

  • 相关阅读:
    linux下安装tomcat
    linux 中安装mysql8.0
    国家助学贷款
    语句摘录
    Java 今天是否为节假日
    Jfinal框架登陆页面的图形验证码
    ActiveRecord初始化,可以实现jfinal系统启动完成后,再建立数据库连接
    socket 通讯
    datatable的excel导入,其中有关于datatables的很多参数设置
    jfinal form表单提交文件
  • 原文地址:https://www.cnblogs.com/fulitaiblogs/p/3640389.html
Copyright © 2011-2022 走看看