Java基礎: 靜態與動態代碼塊

來源:互聯網
上載者:User

定義:在定義屬性的位置上,在任何方法之外,定義一個代碼塊  

種類:分為兩類即動態代碼塊、靜態代碼塊

<1> 動態初始代碼塊:在初始化屬性之前調用初始化代碼塊  {……}
<2> 靜態初始代碼塊:在類載入時運行    static{……}  只被運行一次,往往用作一個類的準備工作

範例程式碼:

package mark.zhang;<br />public class Linux {<br />/**<br /> * 動態代碼塊<br /> */<br />{<br />System.out.println("--動態初始化代碼塊--");<br />}</p><p>/**<br /> * 靜態代碼塊<br /> */<br />static {<br />System.out.println("--靜態初始化代碼塊--");<br />}</p><p>/**<br /> * 測試<br /> *<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />Linux linux = new Linux();<br />}<br />}<br /> 

執行結果:

--靜態初始化代碼塊--<br />--動態初始化代碼塊-- 

從結果看出,建立Linux類的執行個體時載入這個類,從而代碼塊執行,只是靜態代碼塊先於動態代碼塊之前執行。那麼,我們思考兩個問題,類何時被載入,代碼塊、構造方法以及成員變數之間的執行順序是誰先誰後??汗,別急,往下看。

先說一說類載入時機吧!!

(1)new 一個對象的時候,載入

(2)沒有建立對象,訪問類中靜態方法(final和非final的均可以)和靜態屬性(不可以被final修飾,final修飾的靜態屬性是在常量池裡),載入

(3)聲明一個類的引用,不載入

(4)建立子類,先載入父類,再載入子類

(5)父類中的公開靜態方法,子類繼承,使用子類的類名調用此方法,載入父類

 注意,這裡需要滿足兩個條件:

 <a> 子類不可以重寫該靜態方法,其實父類的靜態方法子類是不可以重寫只可以繼承的。即使重寫也要加上static關鍵字。那麼也就說明父類的靜態方法是不可以被子類重寫的,子類重寫的這個靜態方法稱之為子類自己的靜態方法(只不過和父類的該靜態方法重名罷了!!)

 <b>  main方法不可以在子類中,看例子代碼,如下:

 package mark.zhang;<br />public class Linux {<br />/**<br /> * 動態代碼塊<br /> */<br />{<br />System.out.println("--父類Linux--動態初始化代碼塊--");<br />}</p><p>/**<br /> * 靜態代碼塊<br /> */<br />static {<br />System.out.println("--父類Linux--靜態初始化代碼塊--");<br />}</p><p>static void get() {<br />System.out.println("--父類Linux--get()");<br />}<br />}<br />class Ubuntu extends Linux {</p><p>/**<br /> * 動態代碼塊<br /> */<br />{<br />System.out.println("--子類Linux--動態初始化代碼塊--");<br />}</p><p>/**<br /> * 靜態代碼塊<br /> */<br />static {<br />System.out.println("--子類ubuntu靜態初始化代碼塊--");<br />}<br />}<br />class Test {<br />/**<br /> * 測試<br /> *<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />Ubuntu.get();<br />}<br />}<br />

在主函數中運行以下代碼:

//載入了父類之後,虛擬機器已經知道m()方法的調用了,就不會再載入子類,消極式載入Ubuntu.get();   

運行結果:

--父類Linux--靜態初始化代碼塊--<br />--父類Linux--get()
(6)沒有建立對象,訪問類中靜態常量(能計算出結果的常量,在編譯的時候會用計算出來的結果替換運算式),不載入 

(7)沒有建立對象,訪問類中靜態常量(不確定的值),載入   

關於(6)(7),舉兩個個小例子吧??!!!

package my.test;<br />public class FinalTest {<br />// 編譯時間常量,編譯器在編譯時間會將所有用到該變數的地方替換成相應的字面值<br />public static final int a = 4+4;</p><p>static {<br />System.out.println("--static code--");<br />}<br />}<br />class Test {<br />public static void main(String[] args) {<br />System.out.println("FinalTest.a= " + FinalTest.a);<br />}<br />} 

該例子中沒有執行靜態代碼塊,正如(6)所說。

運行結果:

FinalTest.a= 8 

再看一個例子,來說明(7)的正確性!!!

package my.test;<br />public class FinalTest {<br />// 運行時常量,在啟動並執行時候才能確定<br />public static final int a = 4 + Math.abs(1);</p><p>static {<br />System.out.println("--static code--");<br />}<br />}<br />class Test {<br />public static void main(String[] args) {<br />System.out.println("FinalTest.a= " + FinalTest.a);<br />}<br />} 

運行結果,執行靜態代碼塊內容。

--static code--<br />FinalTest.a= 5 

ok,上面說的都是關於類的載入時機問題,接著說說代碼塊、構造方法以及成員變數之間的執行順序的問題。要想說明白這個問題,需要從兩個方面說,一個是單純的一個類,另一個就是一個類與另一個類的繼承。

<1> 單純的一個類

package mark.zhang;<br />public class Linux {<br />// 靜態成員變數<br />public static String name = "Linux OS";<br />// 一般變數<br />public int size = 2;</p><p>public Linux() {<br />System.out.println("--父類Linux--構造方法--");<br />}</p><p>/**<br /> * 動態代碼塊<br /> */<br />{<br />System.out.println("--父類Linux--動態初始化代碼塊--");<br />}</p><p>/**<br /> * 靜態代碼塊<br /> */<br />static {<br />System.out.println("--父類Linux--靜態初始化代碼塊--");<br />}</p><p>} 

測試一下,呵呵!!

class Test {<br />/**<br /> * 測試<br /> *<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />new Linux();<br />}<br />} 

測試結果,如下:

--父類Linux--靜態初始化代碼塊--<br />--父類Linux--動態初始化代碼塊--<br />--父類Linux--構造方法-- 

<2> 具有繼承關係的兩個類

package mark.zhang;<br />public class Linux {<br />// 靜態成員變數<br />public static String name = "Linux OS";<br />// 一般變數<br />public int size = 2;</p><p>public Linux() {<br />System.out.println("--父類Linux--構造方法--");<br />}</p><p>/**<br /> * 動態代碼塊<br /> */<br />{<br />System.out.println("--父類Linux--動態初始化代碼塊--");<br />}</p><p>/**<br /> * 靜態代碼塊<br /> */<br />static {<br />System.out.println("--父類Linux--靜態初始化代碼塊--");<br />}</p><p>}<br />class Ubuntu extends Linux {</p><p>public Ubuntu() {<br />System.out.println("--子類Ubuntu--構造方法--");<br />}</p><p>/**<br /> * 動態代碼塊<br /> */<br />{<br />System.out.println("--子類Ubuntu--動態初始化代碼塊--");<br />}</p><p>/**<br /> * 靜態代碼塊<br /> */<br />static {<br />System.out.println("--子類ubuntu靜態初始化代碼塊--");<br />}<br />}<br />class Test {<br />/**<br /> * 測試<br /> *<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />new Ubuntu();<br />}<br />}<br /> 

執行結果,如下:

--父類Linux--靜態初始化代碼塊--<br />--子類ubuntu靜態初始化代碼塊--<br />--父類Linux--動態初始化代碼塊--<br />--父類Linux--構造方法--<br />--子類Ubuntu--動態初始化代碼塊--<br />--子類Ubuntu--構造方法--<br /> 

至於,代碼塊與成員變數之間誰先誰後,其實是與它們在類中聲明順序有關的。現在以一個小例子說明問題:

package mark.zhang;<br />public class Linux {//靜態與非靜態成員變數與靜態代碼塊、非靜態代碼塊的執行順序與其聲明順序有關</p><p>RedHat rh1 = new RedHat("非靜態成員變數rh1");<br />static RedHat rh11 = new RedHat("靜態成員變數rh11");</p><p>public Linux() {<br />System.out.println("--父類Linux--構造方法--");<br />}</p><p>/**<br /> * 動態代碼塊<br /> */<br />{<br />System.out.println("--父類Linux--動態初始化代碼塊--");<br />}</p><p>/**<br /> * 靜態代碼塊<br /> */<br />static {<br />System.out.println("--父類Linux--靜態初始化代碼塊--");<br />}</p><p>RedHat rh2 = new RedHat("非靜態成員變數rh2");<br />static RedHat rh22 = new RedHat("靜態成員變數rh22");<br />}<br />class RedHat {<br />static int times = 1;<br />public RedHat(String info) {<br />System.out.println(info + ", the order " + (times++));<br />}<br />} 

測試:

class Test {<br />/**<br /> * 測試<br /> *<br /> * @param args<br /> */<br />public static void main(String[] args) {<br />new Linux();<br />}<br />} 

運行結果:

靜態成員變數rh11, the order 1<br />--父類Linux--靜態初始化代碼塊--<br />靜態成員變數rh22, the order 2<br />非靜態成員變數rh1, the order 3<br />--父類Linux--動態初始化代碼塊--<br />非靜態成員變數rh2, the order 4<br />--父類Linux--構造方法-- 

 

 部落格分享:

java類載入全過程(http://my.oschina.net/volador/blog/87194)

 

 

 

 

 

 

 

 

 

 

 

 


 


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.