2010-07-04 123 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