有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何用try/catch最优雅地围绕代码

我在使用try and catch时经常遇到一些问题:

1)一些变量需要在try括号内声明,否则它们将不在范围内
2) 最终,即使我的return语句最终也必须在try括号中,但该方法不会返回任何内容

解决这类问题的正确方法是什么

导致此问题的方法示例如下。它需要处理FileNotFoundException和IOException。我怎样才能最优雅地做到这一点

public static String getContents (File file) {
      BufferedReader reader = new BufferedReader(new FileReader(file));
      String contents = new String();
      while (reader.ready())
        contents += reader.readLine();
      return contents;
    }

共 (6) 个答案

  1. # 1 楼答案

    这里缺少的是一个简单实用程序,它大大简化了清理:

    public static void closeAndLog(Closable c) {
        if ( c == null )
            return;
    
        try { 
            c.close() 
        } catch ( IOException e) {
            LOGGER.warn("Failed closing " + c +, e);
        }
    }
    

    这样,您的代码可以变成:

    public static String getContents (File file) throws IOException {
    
        BufferedReader r = null;
    
        try { 
            r = new BufferedReader(...);
            // do stuff
        } finally {
            closeAndLog(r);
        }
    }
    
  2. # 2 楼答案

    您可以按如下方式进行处理:

    StringBuilder contents = new StringBuilder();
    BufferedReader reader;
    
    try {
       reader = new BufferedReader(new FileReader(file));
    
       while (reader.ready()) {
          contents.append(reader.readLine());
       }
    
    } catch (FileNotFoundException fne) {
       log.warn("File Not Found", fne);
    } catch (IOException ioe) {
       log.warn("IOException", ioe);
    } 
    
    return contents.toString();
    

    在上述情况下,您可能应该使用StringBuilder,而不是字符串,这样在性能方面会更好

  3. # 3 楼答案

    public static String getContents (File file) {
        String contents = new String();
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader(file));
            while (reader.ready())
                contents += reader.readLine();
        }
        catch (FileNotFoundException ex) {
            // handle FileNotFoundException
        }
        catch (IOException ex) {
            // handle IOException
        }
        finally {
            if (reader != null) {
                try {
                    reader.close();
                }
                catch (IOException ex) {
                    // handle IOException
                }
            }
        }
        return contents;
    }
    

    我添加了一个finally块来关闭BufferedReader,尽管您没有在代码中这样做。我还建议您使用StringBuilder而不是String串联,但有人已经指出了这一点。reader的声明和非专业化在try块之外,这仅仅是因为我添加了finally块;否则,可以在try块内声明引用reader

    我没有处理例外情况,我认为这与你的问题无关

  4. # 4 楼答案

    如果不需要在getContents方法中进行异常处理,还有一个选项--向该方法添加throws子句以使该方法引发异常:

    public static String getContents (File file)
        throws IOException, FileNotFoundException {
    

    这样,调用方法的代码将处理Exception而不是方法本身。如果Exception被抛出给调用它的方法,那么在该方法中不需要try/catch

    这可能是也可能不是处理这种情况的理想方式,这取决于该方法的预期行为

    编辑

    仔细想想,让方法抛出异常可能是个好主意。我认为D.Shawley的评论很好地总结了这一点——“异常处理应该意味着只在有意义的地方处理异常。”

    在本例中,getContents方法似乎获取指定的File的内容,并向调用者返回一个String

    如果要在getConents方法中执行异常处理,则传达错误已发生的唯一方法是向调用方返回某种预先确定的值,例如null,以通知发生了错误

    但是,通过让方法本身将异常抛出回调用方,调用方可以选择相应地作出反应:

    try {
        String contents = getContents(new File("input.file"));
    } catch (IOException ioe) {
        // Perform exception handling for IOException.
    } catch (FileNotFoundException fnfe) {
        // Inform user that file was not found.
        // Perhaps prompt the user for an alternate file name and try again?
    }
    

    与其让setContents方法拿出自己的协议来通知发生了错误,不如将IOExceptionFileNotFoundException返回给方法调用方,这样就可以在可以执行适当替代操作的地方执行异常处理

    只有在可以进行一些有意义的处理时,才应执行异常处理

  5. # 5 楼答案

    您可以尝试将return语句移动到finally块中

  6. # 6 楼答案

    关于变量范围,我不确定是否有更优雅的方法。通常情况下,我会考虑在发生错误时返回的值是什么,然后将变量分配给该值

    关于return语句,如果您使用我上面的建议,那么您可以在try/catch块之后返回

    所以,如果我使用空返回值来指示错误,我会这样做

    public static String getContents (File file) {
        String contents = null;
        try {        
            BufferedReader reader = new BufferedReader(new FileReader(file));
            contents = new String();
            while (reader.ready())
                contents += reader.readLine();
        } catch (Exception e) {
            // Error Handling
        }
        return contents;
    }