2013-02-23 75 views
7

根據JLS:如果已命名類的實例變量初始值設定項或實例初始值設定項可以拋出已檢查的異常類,則會出現編譯時錯誤,除非顯式聲明該異常類或其某個超類在它的類的每個構造函數的throws子句中,並且該類至少有一個顯式聲明的構造函數。檢查異常和初始化塊

所以,如果我這樣做 -

class A{ 
{ 
    throw new FileNotFoundException(); 
} 
public A() throws IOException{ 
    // TODO Auto-generated constructor stub 
} 
} 

這給出了一個編譯時錯誤「初始化必須正常完成」

class A{ 
{ 
    File f=new File("a"); 
    FileOutputStream fo=new FileOutputStream(f); 
    fo.write(3); 
} 
public A() throws IOException{ 
    // TODO Auto-generated constructor stub 
} 
} 

這段代碼並不顯示任何編譯時錯誤。爲什麼前面的代碼沒有編譯,即使我已經在構造函數中聲明瞭throws子句?

+0

你告訴初始化塊拋出無條件異常,你還期望什麼? – skuntsel 2013-02-23 15:40:23

回答

4

應該有一些條件,當初始化器可以真正完成沒有任何異常。

在你的情況下,它不可能發生。

嘗試:

if(/*condition-to-fail*/) { 
    /*Not always, only when something is wrong. Compiler knows that.*/ 
    throw new FileNotFoundException(); 
} 

更新:

下面的語句實際上是拋出異常。

throw new FileNotFoundException(); 

所以沒有條件你的程序執行總是在那裏結束。

雖然在下面 -

FileOutputStream fo = new FileOutputStream(f); 

構造FileOutputStream(File)並不總是拋出該異常。

public FileOutputStream(File file) throws FileNotFoundException中的throws子句只是說它可能會引發該異常,並且只有在運行時文件沒有找到時纔會執行該操作。

+0

+1有效。但爲什麼我們需要有條件語句??不能只是拋出異常工作? – PermGenError 2013-02-23 15:40:36

+2

@PremGenError:這就像在沒有條件檢查的返回語句之後編寫代碼一樣。編譯器也可以檢測到,在這種情況下也是如此。 – 2013-02-23 15:42:27

+0

不錯...謝謝:) – PermGenError 2013-02-23 15:43:11

2

http://docs.oracle.com/javase/specs/jls/se7/html/jls-8.html#jls-8.6

It is a compile-time error if an instance initializer cannot complete normally

http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.21

A non-empty block that is not a switch block can complete normally iff the last statement in it can complete normally.

...

The if statement, whether or not it has an else part, is handled in an unusual manner. For this reason, it is discussed separately at the end of this section.

...

in order to allow the if statement to be used conveniently for "conditional compilation" purposes, the actual rules differ.

...

+0

+1僅給出實際原因的答案。 – assylias 2013-04-01 10:12:55

1

在第一個案例編譯器已經知道實例初始化是永遠不會因爲你已經明確地拋出FileNotFoundException那邊正常完成。你可以說它是編譯器的智能代碼評估。但是如果你讓編譯器相信實例初始化器有成功完成的機會,那麼編譯器在編譯時不會抱怨。例如,在下面給出的代碼中,儘管文件IDonotexist.txt在我的目錄中不存在,我相信它會拋出FileNotFoundException,但編譯器仍然會讓它成功編譯。 爲什麼?因爲在執行代碼期間檢查文件的存在,而不是在編譯期間檢查。

class A 
{ 
    { 
     FileReader fr = new FileReader(new File("IDonotexist.txt")); 
    } 
    public A() throws IOException 
    { 
     // TODO Auto-generated constructor stub 
    } 
    public static void main(String st[])throws Exception 
    { 
     A a = new A(); 
    } 
} 

這與最終變量初始化的情況類似。在下面的代碼實施例,編譯器將顯示編譯時錯誤

public void calling() 
    { 
     final int i; 
     int k = 90; 
     if (k == 90) 
     { 
      i = 56; 
     } 
     System.out.println(i);//Compiler will show error here as: variable i might not have been initialized 
    } 

但是,如果我與if(true)替換條件if (k == 90)然後編譯器將不顯示錯誤。因爲編譯器現在知道i肯定會被分配一些值。