<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    上善若水
    In general the OO style is to use a lot of little objects with a lot of little methods that give us a lot of plug points for overriding and variation. To do is to be -Nietzsche, To bei is to do -Kant, Do be do be do -Sinatra
    posts - 146,comments - 147,trackbacks - 0

    問題重現

    讓我們先來看一下以下的程序:

     1 public class StaticInitSequence {
     2     //-------------------Static fields-------------------
     3     private static int staticIntVar = 10;
     4     private static int staticComputeIntVar = (int)(Math.random() * 10);
     5     private static String staticStrVar = "Static field init(before)";
     6     private static Object staticRefVar = new Object();
     7    
     8     static {
     9        staticIntVar = 20;
    10        staticStrVar = "Static block init(before)";
    11        staticAfterIntVar = 40;
    12        staticAfterStrVar = "Static block init(after)";
    13     }
    14    
    15     private static int staticAfterIntVar = 30;
    16     private static String staticAfterStrVar = "Static field init(after)";
    17    
    18     //---------------------Instance fields----------------
    19     private int fieldIntVar = 100;
    20     private int fieldComputeIntVar = (int)(Math.random() * 100);
    21     private String fieldStrVar = "Instance field init(before)";
    22    
    23     public StaticInitSequence() {
    24        fieldIntVar = 200;
    25        fieldStrVar = "Constructor field init(before)";
    26       
    27        fieldAfterIntVar = 400;
    28        fieldAfterStrVar = "Constructor field init(after)";
    29     }
    30    
    31     private int fieldAfterIntVar = 300;
    32     private String fieldAfterStrVar = "Instance field init(after)";
    33    
    34     public void print() {
    35        System.out.println("----------------Static Fields------------");
    36        System.out.println("staticIntVar: " + staticIntVar);
    37        System.out.println("staticComputeIntVar: " + staticComputeIntVar);
    38        System.out.println("staticStrVar: " + staticStrVar);
    39        System.out.println("staticRefVar: " + staticRefVar);
    40        System.out.println("staticAfterIntVar: " + staticAfterIntVar);
    41        System.out.println("staticAfterStrVar: " + staticAfterStrVar);
    42       
    43        System.out.println("-----------------Instance Fields---------");
    44        System.out.println("fieldIntVar : " + fieldIntVar);
    45        System.out.println("fieldComputeIntVar : " + fieldComputeIntVar);
    46        System.out.println("fieldStrVar : " + fieldStrVar);
    47        System.out.println("fieldAfterIntVar : " + fieldAfterIntVar);
    48        System.out.println("fieldAfterStrVar : " + fieldAfterStrVar);
    49     }
    50 }

    如果我們調用以上類的print()方法(new StaticInitSequence().print()),會有什么樣的結果呢?

    我自認為,直接對一個字段初始化是編譯器提供支持的一種編程方式,這種編程方式可以提高代碼的可讀性,因為用戶可以直接知道一個字段的初始值,而不用到構造函數或者靜態語句塊里面去找。在Java中,實際編譯后的二進制文件中,所有的字段初始化語句都放在了初始化函數中(類(靜態)初始化函數(<clinit>)或者實例初始化(構造函數/<init>)函數)。因此在我的邏輯思維中,在源代碼中,初始化函數應該可以改變字段初始化中的值,這樣還就可以在字段初始化中提供一個初始值,而在初始化函數中根據需要改變它。然而另我感到意外的是Java中只有實例初始化機制是這樣實現的,而靜態字段初始化中沒有實現這種機制(在C#中不管實例初始化和靜態初始化都實現了這種機制),靜態字段初始化的順序是完全根據源代碼中定義順序來初始化的;從耦合的角度,這就是一個順序耦合的典型。不知道為什么Java要這樣實現,是否它有其他方面的問題的考慮?亦或是Java設計者或者Java編譯器設計者的一個失誤?不管怎么樣,用sunjavac編譯出來的以上程序的運行結果如下:

    ----------------Static Fields------------
    staticIntVar: 
    20
    staticComputeIntVar: 
    7
    staticStrVar: Static block init(before)
    staticRefVar: java.lang.Object@14318bb
    staticAfterIntVar: 
    30
    staticAfterStrVar: Static field init(after)
    -----------------Instance Fields---------
    fieldIntVar : 
    200
    fieldComputeIntVar : 
    8
    fieldStrVar : Constructor field init(before)
    fieldAfterIntVar : 
    400
    fieldAfterStrVar : Constructor field init(after)

     

    問題解釋:

    從以上程序生成的二進制代碼就可以很好的解釋以上的結果:

    <clinit>:
       
    //staticIntVar = 10
         0 bipush 10
         
    2 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticIntVar : int [22]
          
    // staticComputeIntVar = (int)(Math.random() * 10)
         5 invokestatic java.lang.Math.random() : double [24]
         
    8 ldc2_w <Double 10.0> [30]
        
    11 dmul
        
    12 d2i
        
    13 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticComputeIntVar : int [32]
        
    //staticStrVar = “Static field init(before)”
        16 ldc <String "Static field init(before)"> [34]
        
    18 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticStrVar : java.lang.String [36]
        
    //staticRefVar = new Object();
        21 new java.lang.Object [3]
        
    24 dup
        
    25 invokespecial java.lang.Object() [38]
        
    28 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticRefVar : java.lang.Object [41]
        
    //staticIntVar = 20
        31 bipush 20
        
    33 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticIntVar : int [22]
        
    //staticStrVar = “Static block init(before)”
        36 ldc <String "Static block init(before)"> [43]  
        
    38 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticStrVar : java.lang.String [36]
        
    //staticAfterIntVar = 40
        41 bipush 40
        
    43 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticAfterIntVar : int [45]  
        
    //staticAfterStr = “Statci block init(after)”
        46 ldc <String "Static block init(after)"> [47
        
    48 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticAfterStrVar : java.lang.String [49]
        
    //staticAfterIntVar = 30
        51 bipush 30
        
    53 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticAfterIntVar : int [45]
        
    //staticAfterStrVar = “Static field init(after)”
        56 ldc <String "Static field init(after)"> [51]
        
    58 putstatic org.levin.insidejvm.miscs.staticinit.StaticInitSequence.staticAfterStrVar : java.lang.String [49]
        
    61 return
     
    <init>:
           
    //invoke base constructor
         0  aload_0 [this]
         
    1 invokespecial java.lang.Object() [38]
         
    4 aload_0 [this]
           
    //fieldIntVar = 100
         5 bipush 100
         
    7 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldIntVar : int [55]
           
    //fieldComputeIntVar = (int)(Math.random() * 100)
        10 aload_0 [this]
        
    11 invokestatic java.lang.Math.random() : double [24]
        
    14 ldc2_w <Double 100.0> [57]
        
    17 dmul
        
    18 d2i
        
    19 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldComputeIntVar : int [59]
    //fieldStrVar = “Instance field init(before)”
        22 aload_0 [this]
        
    23 ldc <String "Instance field init(before)"> [61]
        
    25 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldStrVar : java.lang.String [63]
    //fieldAfterIntVar = 300
        28 aload_0 [this]
        
    29 sipush 300
        
    32 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldAfterIntVar : int [65]
    //fieldAfterStrVar = “Instance field init(after)”
        35 aload_0 [this]
        
    36 ldc <String "Instance field init(after)"> [67]
        
    38 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldAfterStrVar : java.lang.String [69]
    //fieldIntVar = 200
        41 aload_0 [this]
        
    42 sipush 200 
        
    45 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldIntVar : int [55]
    //fieldStrVar = “Constructor field init(before)”
        48 aload_0 [this]
        
    49 ldc <String "Constructor field init(before)"> [71]
        
    51 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldStrVar : java.lang.String [63]
    //fieldAfterIntVar = 400
        54 aload_0 [this]
        
    55 sipush 400
        
    58 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldAfterIntVar : int [65]
    //fieldAfterStrVar = “Constructor field init(after)”
        61 aload_0 [this]
        
    62 ldc <String "Constructor field init(after)"> [73]
        
    64 putfield org.levin.insidejvm.miscs.staticinit.StaticInitSequence.fieldAfterStrVar : java.lang.String [69]
        
    67 return

    問題延伸

    在這里,細心的人可能還會想到另外一個問題,如果StaticInitSequence類還有父類,并且父類中同同時有靜態成員初始化,靜態語句塊初始化,實例成員初始化,構造函數初始化,那會這樣的順序會是怎么樣的呢?在Java中,保證父類的初始化要早于子類的初始化,因而如果有父類存在的話,一定是先父類初始化做好以后才做子類的初始化(這一點和C#又有略微的不同,在C#中,子類的字段初始化語句要早于父類的初始化語句和構造函數),并且是先靜態初始化再實例初始化。

                                                                                                                        于2010年9月24日
    注:這些文章都是前些時候寫的,之前博客很亂,也都是隨便貼一些自己寫的或轉載的,還有一些則是沒有貼出來過的。現在打算好好整理一下,完整的記錄自己的一些學習歷程,而每次看到過去的時間,則讓我想起以前的日子,因而我對時間一直是很重視的,所以每篇都著名寫的日期,直到最先的文章出現。:)

    posted on 2011-06-20 22:53 DLevin 閱讀(2775) 評論(2)  編輯  收藏 所屬分類: Core Java

    FeedBack:
    # re: Static變量和實例變量的初始化順序問題
    2011-06-21 09:54 | 成都制鞋培訓
    有點高級,看不懂  回復  更多評論
      
    # re: Static變量和實例變量的初始化順序問題
    2011-06-21 22:41 | CodeMe
    不錯  回復  更多評論
      
    主站蜘蛛池模板: 高h视频在线免费观看| 无码日韩精品一区二区免费| 亚洲娇小性xxxx| 亚洲综合婷婷久久| 国产黄色一级毛片亚洲黄片大全| 曰批全过程免费视频在线观看| 成人无码WWW免费视频| 人成电影网在线观看免费| 亚洲日本VA午夜在线电影| 亚洲国产情侣一区二区三区| 国产精品亚洲片在线观看不卡 | 成年女人18级毛片毛片免费观看| 国产免费网站看v片在线| 特级毛片爽www免费版| 精品亚洲国产成人av| 亚洲综合激情五月色一区| 亚洲人成影院在线高清| 久久精品国产亚洲AV大全| 久久国产亚洲观看| 亚洲级αV无码毛片久久精品| 亚洲电影日韩精品| 国产99视频精品免费视频7| 成年女人毛片免费播放人| 我们的2018在线观看免费高清| 99爱在线观看免费完整版| 免费萌白酱国产一区二区三区| 两个人www免费高清视频| 国产精品玖玖美女张开腿让男人桶爽免费看 | 最近最新的免费中文字幕| 国产免费AV片在线播放唯爱网| 67pao强力打造高清免费| 59pao成国产成视频永久免费| 91精品全国免费观看含羞草| 免费无码VA一区二区三区| 中文字幕免费视频| 精品国产污污免费网站aⅴ| 精品免费人成视频app| 免费大片黄在线观看yw| 日本精品人妻无码免费大全| 女人18毛片水真多免费看| 国产青草视频免费观看97|