qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          Java中的static

            學習本文你到底要學到什么:

            1、 static在java中到底代表什么,為何要用它?

            2、 static在java中怎么用?

            3、 static 有那些特點和使用的“局限”

            1、 static在java中到底代表什么,為何要用它?

            static――靜態――“指定位置“

            首先,我們來看看java的內存:java把內存分為棧內存和堆內存,棧內存用來存放一些基本類型的變量和數組及對象的引用變量,而堆內存主要是來放置對象的。

            用static的修飾的變量和方法,實際上是指定了這些變量和方法在內存中的“固定位置”-static storage。既然要有“固定位置”那么他們的“大小”似乎就是固定的了,有了固定位置和固定大小的特征了,在棧中或堆中開辟空間那就是非常的方便了。如果靜態的變量或方法在不出其作用域的情況下,其引用句柄是不會發生改變的。

            我們常看到:static變量有點類似于C中的全局變量的概念;靜態表示的是內存的共享,就是它的每一個實例都指向同一個內存地址。把static拿來,就是告訴JVM它是靜態的,它的引用(含間接引用)都是指向同一個位置,在那個地方,你把它改了,它就不會變成原樣,你把它清理了,它就不會回來了。我們常可看到類似以下的例子來說明這個問題:

          package com.meritit.test;

          class Student {
           static int numberOfStudents = 0;

           Student() {
            numberOfStudents++;
           }
          }

            每一次創建一個新的Student實例時,成員numberOfStudents都會不斷的遞增,并且所有的Student實例都訪問同一個numberOfStudents變量,實際上int numberOfStudents變量在內存中只存儲在一個位置上。

            多個實例共享一個變量似乎不足以讓我們對static那么的熱情,實際上java引入static卻有另外的含義:

            (1)、引用static的方法和變量,不需要和實例捆綁在一起,這可以提高代碼的編寫的效率,這樣的例子我們隨處可見;

            (2)、java的主類中main()方法本身就是一個static的,所以main方法的執行就是在沒有產生新的實例的情況;對于靜態的東西,JVM在加載類時,就在內存中開辟了這些靜態的空間,所以雖沒有靜態的main()方法但是程序還是執行了,不過拋出來了無main()方法的異常。這也不知算不算是java的一個漏洞;

            (3)、如果需要創建一個脫離于實例的變量或方法(只與整個類有關),那么用static作修飾是再好不過了,如我們經常看到要統計實例實現的個數(通常的例子就是計數)。

            (4)、使用一種靜態的方法的編程通常叫做防御(defensive)編程,它可以在API供應商突然中斷支持的情況下保護代碼
               static在java中怎么用?

            使用static時,要記著我闡述的static代表什么。

            static使用非常的簡單,如果要修飾一個靜態塊只需:staic {……..}即可(常用靜態塊來初始化一些變量); 靜態方法就參照main()的形式:訪問標識 static returnType method(…) {};靜態變量就是:static type fields;

            在使用靜態的方法時,可以直接用類名來引用,不需要創建實例(當然創建實例也是可以的),例如,System.out,String.valueOf()等等。

            3、 static 有那些特點和使用的“局限”?

            從上面的分析可知,static的東西在類加載時,就分配了內存空間,即編譯時就為這些成員變量的實例分配了空間。

            那么在static塊內和方法體內,我們能給它放一個在內存中還沒有著落的變量?顯然與我們先前所說的相左。static的東西,人家是在static storage中有“指定位置“的,如果我們茫然的在static的作用域中放置一個普通的變量,那么編譯時JVM就毫不客氣的給你個異常:

            non-static variable a cannot be referenced from a static context或non-static method Test() cannot be referenced from a static context(注:Test()是我試驗時的一個例子),除非我在static中現場開辟空間,用new來要內存。

            對于static的初始化問題,我們還是值得討論的。現看下面的例子

          package com.meritit.test;

          public class StaticInit
          {
              static int i;
              int a;
              public StaticInit()
              {
                 a=6;
                 System.out.println("a 的初始化"+a);
              } 
              public static void main(String[] args)
             {
               new StaticInit();
             }
             static 
             {
                i=5;
                System.out.println("i 的初始化"+i);
             }
          }

            運行結果如下:

            i 的初始化5

            a 的初始化6

          靜態塊的初始化要早于非靜態的,原因就是在于這些東西是在類裝載時就開始初始化了。

            說起static的“局限“,總結起來就是:在static的方法中僅能夠調用其他的static方法和static變量;在static方法中不能以任何方式引用this或super;static變量在定義時必須進行初始化,并且初始化的時間早于非靜態。還有一個局限我需要具體的說明一下,static的變量的初始化僅能一次,如下例:

          package com.meritit.test;

          public class Static {
           T1 t1 = new T1(2);
           T1 t2 = new T1(3);
           T1 t3 = new T1(4);

           public Static() {
            System.out.println("t1: " + t1.t);
            System.out.println("t2: " + t2.t);
            System.out.println("t3: " + t3.t);
           }

           public static void main(String args[]) {
            new Static();
           }
          }

          class T1 {
           static int t = 1;

           T1(int b) {
            t = b;
           }
          }

            運行結果:

            t1: 4

            t2: 4

            t3: 4

            該static變量只是接受了最后一次的初始化.實際這還是我們先前提到的多個實例共享一個靜態的變量的問題。

            總之,static就是給我們一個這樣的忠告:static的東西在編譯時,就已向內存要到了存取空間了。

          posted on 2013-08-19 10:22 順其自然EVO 閱讀(164) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          <2013年8月>
          28293031123
          45678910
          11121314151617
          18192021222324
          25262728293031
          1234567

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 麻江县| 乌审旗| 广元市| 苍山县| 修武县| 扶余县| 黔江区| 永宁县| 乐东| 上高县| 白银市| 康定县| 崇明县| 阜宁县| 五指山市| 陆川县| 疏勒县| 雷山县| 瓮安县| 原阳县| 夏津县| 萝北县| 阜平县| 苗栗市| 泽普县| 昭平县| 兴城市| 凤城市| 邢台市| 西峡县| 铜鼓县| 墨江| 普安县| 临海市| 岚皋县| 安图县| 定边县| 泊头市| 乌拉特后旗| 广水市| 黎川县|