2013-09-16 119 views
15

我這下面的一段代碼:爲什麼變量在調用構造函數之前被初始化?

public abstract class UCMService{ 
    private String service;  

    protected DataMap dataMap = new DataMap(); 

    protected class DataMap extends HashMap<String,String> { 

     private static final long serialVersionUID = 4014308857539190977L; 

     public DataMap(){ 
      System.out.println("11111"); 
      put("IdcService",service); 
     } 
    } 

    public UCMService(String service){ 
     System.out.println("2222"); 
     this.service = service; 
    } 
} 

現在,在控制檯System.out.printlnDataMap的構造函數的UCMService的構造函數之前執行。

我想知道爲什麼會發生。

回答

31

這是因爲在編譯時,編譯器每次都在聲明的地方做初始化移動到你的類的每一個構造。所以UCMService類的構造有效地編譯:

public UCMService(String service){ 
    super(); // First compiler adds a super() to chain to super class constructor 
    dataMap = new DataMap(); // Compiler moves the initialization here (right after `super()`) 
    System.out.println("2222"); 
    this.service = service; 
} 

因此,很明顯DataMap()構造函數UCMService類的print語句之前執行。同樣,如果您的UCMService類中還有其他構造函數,則初始化將移至所有這些構造函數。


讓我們看一個簡單的類的字節碼:

class Demo { 
    private String str = "rohit"; 

    Demo() { 
     System.out.println("Hello"); 
    } 
} 

編譯這個類,並執行命令 - javap -c Demo。你會看到構造函數的後面的字節代碼:

Demo(); 
    Code: 
     0: aload_0 
     1: invokespecial #1 // Method java/lang/Object."<init>":()V 
     4: aload_0 
     5: ldc   #2 // String rohit 
     7: putfield  #3 // Field str:Ljava/lang/String; 
     10: getstatic  #4 // Field java/lang/System.out:Ljava/io/PrintStream; 
     13: ldc   #5 // String Hello 
     15: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 
     18: return 

您可以在第7行看到putfield指令,初始化場str"rohit",這是print語句之前(指令在行15

+0

+1這是一個很好的答案:) – nachokk

+0

啊......這是超級清晰:) –

+0

精彩的解釋。非常感謝Rohit。 –

13

簡短回答
因爲規範是這樣說的。

龍回答
這將是很奇怪的構造函數無法使用內聯初始化領域。

你希望能夠寫出

SomeService myService = new SomeService(); 
public MyConstructor() { 
    someService.doSomething(); 
} 
+0

等待,所以有些人告訴我不要在構造函數中工作。我把這個意思是,只在構造函數中賦值變量。 someService.doSomething()算作工作嗎? – Kammeot

+1

如果doSomething()實際上做了某些事情,那麼是的 - 那是工作。 – nos

+0

@nos如果'doSomething()'沒有做什麼,那麼它應該被重命名爲更具描述性的內容。 – AJMansfield

相關問題