2013-05-12 87 views
0

我正在閱讀Bruce Eckel第4版中的Thinking in Java。在章初始化&清理,頁:189在第二對第一點提到:由於靜態初始化而被調用的構造函數

即使它沒有明確使用static關鍵字構造函數實際上是一個靜態方法。

我有下面的代碼:

class Bar { 
    Bar() { 
     System.out.println("Bar Creation"); 
    } 
} 

class Foo { 
    static int x = 10; 
    static Bar b = new Bar(); 

    Foo() { 
     System.out.println("Foo Creation"); 
    } 
} 

public class Test { 
    public static void main(String[] args) { 
     System.out.println(Foo.x); 
    } 
} 

如果它說的是真的Foo的構造函數應該被調用。我沒有看到下面這段代碼發生。

輸出是:

Bar Creation 
10 

有人能澄清這是什麼意思?

我盡力引用這本書。我不認爲在該陳述之前或之後的部分與該陳述在該問題的背景下有很多相關性。

感謝,

Gudge

+0

感謝您的所有意見。我完全理解,除非創建對象,否則構造函數將不會被調用。那麼這本書中的陳述意味着什麼。 – gudge 2013-05-12 14:39:03

回答

4

Foo()沒有理由因爲您提到課程而被調用。靜態初始化程序static Bar b = new Bar();在加載類時調用;靜態方法由您的代碼調用。

我猜什麼書的意思是,構造像在靜態方法調度是靜態的:那就是,沒有辦法繼承並重寫一個構造函數,調用位置的構造,或者一個靜態方法,總是指編譯時確定的某個特定的類。

(構造函數這staticness是「工廠」的對象,其在它們的實例方法構造對象。動機)

+0

感謝您的解釋。 – gudge 2013-05-12 14:45:48

3

很簡單,因爲你還沒有創建的Foo新實例來訪問它

靜態字段x如果你創造了new Foo()構造函數的代碼會接到電話。由於x是靜態成員字段,因此其不需要以創建持有人類的實例以訪問該字段。

訪問x的另一種方式是新的Foo().x,但不需要創建新對象。

「條形碼創建」打印的原因是,因爲Foo聲明的靜態字段被分配爲。有關初始化規範,請參見JLS 12.4.1

1

構造函數在創建新對象後調用。我不會把它的靜態方法,因爲它必須有一個實例,該實例是通過默認訪問this

public class Main { 
    public Main() { 
     // static methods do not have a `this` 
     System.out.println("Main called" + this.getClass()); 
    } 

    public static void main(String... ignore) { 
     new Main(); 
    } 
} 

如果反編譯的字節代碼,你可以看到static方法

$ javap -c -p -cp . Main 
Compiled from "Main.java" 
public class Main { 
    public Main(); 
    Code: 
     0: aload_0  
     1: invokespecial #1     // Method java/lang/Object."<init>":()V 
     4: getstatic  #2     // Field java/lang/System.out:Ljava/io/PrintStream; 
     7: new   #3     // class java/lang/StringBuilder 
     10: dup   
     11: invokespecial #4     // Method java/lang/StringBuilder."<init>":()V 
     14: ldc   #5     // String Main called 
     16: invokevirtual #6     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
     19: aload_0  
     20: invokevirtual #7     // Method java/lang/Object.getClass:()Ljava/lang/Class; 
     23: invokevirtual #8     // Method java/lang/StringBuilder.append:(Ljava/lang/Object;)Ljava/lang/StringBuilder; 
     26: invokevirtual #9     // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
     29: invokevirtual #10     // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     32: return   

    public static void main(java.lang.String...); 
    Code: 
     0: new   #11     // class Main 
     3: dup   
     4: invokespecial #12     // Method "<init>":()V 
     7: pop   
     8: return   
} 

注:static方法有不同的修飾符。

1

除非您在Foo類上調用new(),否則不會調用構造函數。由於新的關鍵字在內部調用構造函數。您只需使用其名稱訪問類的靜態字段即可,因爲您無需創建實例。

0

你是新newing了富,而不是你newing酒吧作爲一個靜態字段富。您可以訪問某個類中的靜態變量,而無需構建它的一個實例。

0

只有在使用new關鍵字時纔會調用構造函數。既然你沒有做new Foo(),那麼構造函數就不會被調用。

相關問題