2010-07-04 120 views
5

我在處理3個應該處理的異常時執行以下方法時遇到了一些麻煩。 我應該像我正在做的那樣包含try/catch塊嗎?還是應該爲應用程序而不是類設計Java異常處理方法

的方法說我應該實現這個:

public Catalog loadCatalog(String filename) 
     throws FileNotFoundException, IOException, DataFormatException 

此方法加載從目錄的產品指定的存檔的信息,並返回目錄。

從打開文件開始閱讀。然後繼續讀取並處理文件的每一行。

方法String.startsWith被用於確定線路的類型:

  • 如果線的類型是「產品」,該方法readProduct被調用。
  • 如果行的類型是「Coffee」,則調用readCoffee方法。
  • 如果行的類型是「Brewer」,則調用readCoffeeBrewer方法。

生產線處理後,loadCatalog將產品(產品,咖啡或啤酒)添加到產品目錄。

當處理完文件的所有行時,loadCatalog將產品目錄返回給進行調用的方法。

這種方法可以拋出以下例外:

  • FileNotFoundException - 如果不存在指定的文件。
  • IOException - 如果讀取指定文件的信息時發生錯誤。
  • DataFormatException - 如果某行有錯誤(例外必須包含有錯誤的數據線)

這是我到目前爲止有:

public Catalog loadCatalog(String filename) 
     throws FileNotFoundException, IOException, DataFormatException{ 
    String line = ""; 
    try { 
     BufferedReader stdIn = new BufferedReader(new FileReader("catalog.dat")); 
      try { 
       BufferedReader input = new BufferedReader(
        new FileReader(stdIn.readLine())); 
       while(! stdIn.ready()){ 
        line = input.readLine();       
        if(line.startsWith("Product")){ 
         try { 
          readProduct(line); 
         } catch(DataFormatException d){ 
          d.getMessage(); 
         } 
        } else if(line.startsWith("Coffee")){ 
         try { 
          readCoffee(line);        
         } catch(DataFormatException d){ 
          d.getMessage(); 
         } 
        } else if(line.startsWith("Brewer")){ 
         try { 
          readCoffeeBrewer(line); 
         } catch(DataFormatException d){ 
          d.getMessage(); 
         } 
        } 
       } 
      } catch (IOException io){ 
       io.getMessage(); 
      } 
    }catch (FileNotFoundException f) { 
     System.out.println(f.getMessage()); 
    } 
    return null; 
} 

回答

1

一般的想法是,你滲透異常到適當的地方來處理它們。我猜你的導師希望他們能夠主要處理。在這種情況下,我可以猜測,因爲你給出了throws子句。一個簡單的經驗法則是,如果該方法在throws子句中聲明瞭異常,則不會在該方法中捕獲該異常。所以你寫的方法應該沒有catch語句。

要做到這一點,你會改變你的代碼是這樣的:

public Catalog loadCatalog(String filename) 
    throws FileNotFoundException, 
      IOException, 
      DataFormatException 
{ 
    String line = ""; 

    BufferedReader stdIn = new BufferedReader(new FileReader("catalog.dat")); 
    BufferedReader input = new BufferedReader(new FileReader(stdIn.readLine())); 

    while(!stdIn.ready()) 
    { 
     line = input.readLine(); 

     if(line.startsWith("Product")) 
     { 
      readProduct(line); 
     } 
     else if(line.startsWith("Coffee")) 
     { 
      readCoffee(line); 
     } 
     else if(line.startsWith("Brewer")) 
     { 
      readCoffeeBrewer(line); 
     } 
    } 

    return null; 
} 

,然後調用loadCatalog方法(假設主),你會:

try 
{ 
    loadCatalog(...); 
} 
catch(FileNotFoundException ex) 
{ 
    ex.printStackTrace(); 
} 
catch(IOException ex) 
{ 
    ex.printStackTrace(); 
} 
catch(DataFormatException ex) 
{ 
    ex.printStackTrace(); 
} 

的東西代替的printStackTrace適當。

這樣,loadCatalog方法不會處理顯示錯誤消息,因此您可以在GUI或控制檯代碼中調用方法,調用它的代碼可以選擇如何向用戶顯示錯誤(或以某種方式處理它)。

4

這取決於你是否要該類或應用程序的另一部分使用它來處理異常並執行所需的任何操作。

由於將使用loadCatalog()可能將不知道如何處理文件I/O或格式異常做的代碼,就個人而言,我會與創建像CatalogLoadException異常去從內部把它loadCatalog()方法,並將引起異常FileNotFoundException,IOException,DataFormatException)放入其中,同時包含一條信息性消息,具體取決於觸發了哪個異常。

try { 
     ... 
    //do this for exceptions you are interested in. 
    } catch(Exception e) { 
     //maybe do some clean-up here. 
     throw new CatalogLoadException(e); // e is the cause. 
    } 

這樣你loadCatalog()方法纔會拋出一個單一的和有意義的例外。

現在將使用loadCatalog()的代碼只需要處理一個例外:CatalogLoadException

loadCatalog(String filename) throws CatalogLoadException 

這也讓你的方法來隱藏及其實施細則,所以你不必改變其「異常拋出」簽名當底層低的水平結構的變化。請注意,如果您更改了此簽名,則每個代碼片段都需要相應更改以處理您引入的新類型的例外情況。

另請參閱Exception Translation上的此問題。


更新到投擲簽名要求:

如果,以保持該簽名,那麼你真的沒有選擇,只能throw他們的應用和內部不catch他們loadCatalog()方法,否則throws簽名將是無用的,因爲我們不會拋出我們剛纔處理的完全相同的異常。

+0

感謝偉大的忠告,但它聽起來像一個更好的設計技術來拋出僅1例外,處理所有的人。我從現在開始嘗試一下。但是,我忘了提及這個特定的練習(對於學校),我必須完全按照描述來實現該方法,因爲之後我必須通過預製Tesfile應用程序來運行它,並確保它編譯完成。 – edu222 2010-07-04 17:03:55