2

老實說,我對異常處理並不是很有經驗,因爲通常對於我的懶惰,我傾向於不處理異常。所以這是一個非常基本的問題。在構造函數中的異常處理

我想知道什麼是做到這一點的情況最乾淨的方式,異常處理方法:

我有一個類(CONFIGMANAGER)讀取它的構造函數中的一個文件,並需要一個文件存在於正確構造,作爲構造函數參數給出。 如果文件不存在,我想捕獲FileNotFoundException,使用一些默認值創建文件,並繼續使用現在可用的默認配置文件創建ConfigManager對象。

下面是一些代碼:

class ConfigManager{ 
    ConfigManager(String file){ 
     try{ 
      builder = builderFactory.newDocumentBuilder(); 
      document = builder.parse (new FileInputStream(file)); 
      .... 
     }catch (FileNotFoundException e) { 

     File configFile = new File (file); 

     try { 

      configFile.createNewFile(); 
      BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); 
      writer.write(this.defaultConfig); 
      writer.close(); 


      return new ConfigManager(string); //Here's the problem. I can't do that but I need to try build ConfigManager again. How do that? 

     } catch (IOException e1) { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
    } 
} 

如何構建一個新的CONFIGMANAGER對象時,默認的配置文件創建後? 這是處理此類異常的方法嗎?

在此先感謝

+0

第一個「catch」之後是否有一些代碼丟失? – trashgod 2011-05-16 15:10:08

+0

我認爲在這種情況下最好讓構造函數拋出異常(即不要在構造函數中處理它)。提供另一個不帶File參數的構造函數來創建默認管理器。 – 2011-05-16 15:14:01

回答

4

你可以做的是確保文件存在之前試圖解析它。

FileInputStream fis = null; 
try { 
    fis = new FileInputStream(file); 
} catch (FileNotFoundException e) { 
    BufferedWriter writer = new BufferedWriter(new FileWriter(configFile)); 
    writer.write(defaultConfig); 
    writer.close(); 
    fis = new FileInputStream(file); 
} 

try{ 
    builder = builderFactory.newDocumentBuilder(); 
    document = builder.parse (fis); 
1

解決的辦法是你的構造劃分爲兩個部分。第一部分嘗試從現有文件創建FileInputStream。如果它拋出FileNotFoundException,那麼您創建並填充上面的文件,然後再次打開FileInputStream。第二部分採用第一部分打開的文件FileInputStream(不管它是如何打開的)並繼續初始化。

另一種選擇是將此加載推遲到init()方法,以便類的消費者必須同時創建和初始化其對象。

2

不要在構造函數中讀取文件,創建一個方法(可能是私有的),它可以讀取文件並在ConfigManager上設置值。

然後在構造函數中,您嘗試再次調用構造函數,只需調用該方法即可。

即不要再次調用構造函數。

更新 - 我會組織這樣的代碼:

ConfigManager(String fileName) { 
    File file = new File(fileName); 
    if (!file.exists()){ 
     // create this method -- Im assuming its ok to put the default 
     // config on the path where the file did not exist. 
     createDefaultConfigFile(fileName); 
    } 

    parseConfigFile(fileName, ...); // create this method too 
} 

這顯然是不工作的代碼,我不知道這樣的,據我可以去,你正在做具體是什麼。但它比現在更具可讀性,並且更有組織性。另外,如果指定的配置文件不存在,是否真的想創建一個新的默認配置文件?爲什麼不彈出警告說配置不存在,所以你使用的是默認值,但不寫入默認文件?你可能有理由寫出默認值,如果這是真的,那麼確定,但如果你不需要,不要添加更多的工作...

1

你需要能夠再次調用構造函數,但沒有創建一個新的對象 - 只是在同一個對象上調用它。由於Java不允許你這樣做,所以你必須創建一個輔助方法,將代碼從構造函數移入,然後從構造函數中調用新方法。

這是一種基本技巧,適用於需要實現遞歸的任何情況,但不能直接遞歸。

1

完成此操作的最簡單方法不是執行任何可能導致構造函數中出現異常的操作。如果您在使用對象之前絕對需要執行它們,請在單獨的方法init()中執行它們。

1

嘗試將配置文件的解析委託給其他方法。這樣,您可以檢查文件是否先存在,然後創建默認文件,或將現有文件傳遞給此新方法。

1

那麼,實際上你有一個ConfigManager的新實例後構造函數執行沒有錯誤。所以你所要做的就是去掉有問題的線路。

或考慮使用靜態初始值設定項。當您的應用程序部署/啓動時,這將只檢查一次文件。

1

常爲我的懶惰我傾向於不 處理異常

我建議你先解決懶惰。事實上,你只是爲自己創造更多的工作。

+0

+1是的,我應該。 – Heisenbug 2011-05-17 13:43:27