2009-11-15 85 views
6

有人可以解釋我以下是什麼?Java:什麼是靜態{}?

public class Stuff 
{ 
    static 
    { 
     try 
     { 
      Class.forName("com.mysql.jdbc.Driver"); 
     } 
     catch (ClassNotFoundException exception) 
     { 
      log.error("ClassNotFoundException " + exception.getMessage()); 
     } 
... 
} 

這個靜態{...}是做什麼的?

我知道從C++靜態變量,但是是靜態塊的東西?

這東西什麼時候會被執行?

+0

Dupe。 http://stackoverflow.com/questions/335311/java-static-keyword – finnw 2009-11-15 14:32:10

回答

14

該靜態塊被稱爲class static initializer - 它在第一次加載類時運行(並且它是唯一一次運行[腳註])。

特定模塊的目的是檢查是否MySQL驅動程序在類路徑(並拋出/日誌錯誤,如果它不是)。


[腳註]靜態塊運行每一次的類加載器加載的類(因此,如果你有多個類加載器是彼此(例如不委託例如)不同,它會被執行一次每個

+1

「它在第一次加載類時運行(並且它是唯一運行的時間)。」 - 是否每個加載類的類加載器都運行一次?我知道的技術性,但可能值得一提。 – Grundlefleck 2009-11-15 11:38:18

+0

在這種情況下,檢查MySQL驅動程序並非全部完成:實例化類會自動將其註冊到DriverManager。這是爲了在後面的DB connect()語句中響應MySQL URL所必需的。 – 2009-11-15 11:46:09

+1

如果catch子句拋出一個RunTimeException而不是隻記錄錯誤,則類Stuff的加載將被中止,並且對它的任何引用都將導致運行時的NoClassDefFoundError。 – Henry 2009-11-15 12:02:50

8

靜態初始化塊的主要用途是做各種初始化位,這些位在構造函數中可能不合適,例如構造函數和初始化函數一起將新創建的對象置於完全一致的狀態。

與構造函數相反,例如,靜態初始值設定項s不會被繼承,並且只能在JRE加載和初始化類時執行一次。在上面的例子中,一旦初始化完成,類變量foo將具有值998877。

還要注意的是靜態初始化是在其文本方式出現在源文件中的順序執行。此外,在這些塊之一中不能執行的操作有很多限制,例如不使用檢查的異常,不使用return語句或this和super關鍵字。

+0

*靜態*初始化塊(與構造函數和普通初始化塊相對)實際上與* object *初始化無關。 – Henry 2009-11-15 11:52:19

1

我想補充一點,靜態變量和靜態初始化的出場順序在類加載時執行。所以,如果你的靜態初始化器依賴於一些靜態變量,它必須在特定的靜態塊之前被初始化,

final static String JDBC_DRIVER = getJdbcDriver(); 

static 
{ 
    try 
    { 
    Class.forName(JDBC_DRIVER); 
    } 
    catch (ClassNotFoundException exception) 
    { 
    log.error("ClassNotFoundException " + exception.getMessage()); 
    } 
} 

在本例中getJdbcDriver將在靜態初始化器之前執行。此外,該類中可能有多個靜態初始化器。他們再次按照外觀順序執行。

我也想在這裏提實例初始化的存在,當第一次看到他們做出來的驚喜。它們看起來像類體內的代碼塊,就像這樣。

class MyClass 
{ 
    final int intVar; 

    { 
    intVar = 1; 
    } 
} 

在一般情況下,它們的使用是有點多餘,因爲構造的,但他們是在執行Java的版本封鎖有用。

1

的靜態初始化塊得到執行每當類是將要加載的第一次。如果更高級別的人第一次在課堂上做Class#forName("yourpackage.YourClass")new YourClass(),那麼可能會發生這種情況。

巧合的是,體面的JDBC驅動程序裏面也有類似的東西。他們即使用一個靜態初始化塊登記自己在DriverManager

static { 
    DriverManager.registerDriver(new ThisDriver()); 
} 

所以,每當你做一個Class.forName("somepackage.ThisDriver"),你將有效註冊驅動程序在DriverManager,這樣你可以從它的連接之後。

1

除了以上所述,使用類構造函數和類初始化程序還有一點點不同。我們知道的構造函數通常用於初始化對象,如果我們有靜態變量,那麼通常會使用靜態塊來在加載類時初始化它們。

當我們有靜態變量和靜態塊,然後靜態變量首先初始化,然後塊。

當第一次加載類時,靜態塊在類構造函數之前進行初始化。

0

靜態初始化塊

  • 是一個代碼正常塊

  • 它被封閉在大括號{}

  • 它由靜態關鍵字之前

    class Foo { 
        static { 
         // initialization code goes here: 
         doSomething(); 
        } 
    } 
    
  • 類可以有任意數量的靜態初始化塊

  • 他們可以在類體內

  • ,他們被稱爲在apperence的順序代碼

出現在任何地方有一個替代靜態初始化塊:

  • 寫一個私有靜態方法
  • 並將其分配給靜態類變量

這種方法的優點是,靜態方法可以在以後調用以重新初始化類變量。

class Foo { 
    public static int myVar = initializeClassVariable(); 

    private static int initializeClassVariable() { 
     // initialization code goes here: 
     int v = 255; 
     return v; 
    } 
} 
相關問題