应该组合方法中的多个Try / Catch块

时间:2010-11-14 12:11:22

标签: java

看看我的方法,我不确定我必须使用三个单独的try / catch块。我应该使用唯一的方法吗?什么是好习惯?

public void save(Object object, File file) {    

        BufferedWriter writter = null;

        try {
            writter = new BufferedWriter(new FileWriter(file));
        } catch (IOException e) {
            e.printStackTrace();
        }

        Dictionary dictionary = (Dictionary)object; 
        ArrayList<Card> cardList = dictionary.getCardList();
        for (Card card: cardList) {
            String line = card.getForeignWord() + " / " + card.getNativeWord();
            try {
                writter.write(line);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        try {
            writter.flush();
            writter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

6 个答案:

答案 0 :(得分:11)

您当然不希望三个单独的块与代码一样。在第一个块中,您正在设置错误设置writer,但是在后续块中,您使用 writer,如果第一个块没有意义阻止失败。当发生I / O错误时,你最终会抛出一个NullPointerException - 不理想。 : - )

这个东西有很多风格,但这是对你的功能的一个相当标准的重新解释。它只使用两个块(尽管您可以选择添加第三个块;请参阅代码中的注释):

public void save(Object object, File file) {    

    BufferedWriter writter = null;

    try {
        writter = new BufferedWriter(new FileWriter(file));

        Dictionary dictionary = (Dictionary)object; 
        ArrayList<Card> cardList = dictionary.getCardList();
        for (Card card: cardList) {
            String line = card.getForeignWord() + " / " + card.getNativeWord();
            writter.write(line); // <== I removed the block around this, on
                                 // the assumption that if writing one card fails,
                                 // you want the whole operation to fail. If you
                                 // just want to ignore it, you would put back
                                 // the block.
        }

        writter.flush(); // <== This is unnecessary, `close` will flush
        writter.close();
        writter = null;  // <== null `writter` when done with it, as a flag
    } catch (IOException e) {
        e.printStackTrace(); // <== Usually want to do something more useful with this
    } finally {
        // Handle the case where something failed that you *didn't* catch
        if (writter != null) {
            try {
                writter.close();
                writter = null;
            } catch (Exception e2) {
            }
        }
    }
}

关于finally块的注意事项:在这里,您可能正在处理正常情况(在这种情况下writter将是null),或者您可能正在处理您所做的异常' t catch(这并不罕见,例外的一个主要问题是处理这个级别的适当内容并将其他任何内容传递给调用者)。如果writter!null,请将其关闭。当你关闭它时,任何发生的异常或你会掩盖原来的异常。 (对于这种情况,我有实用功能,可以在吃异常时关闭东西。对我来说,writter = Utils.silentClose(writter); [silentClose总是会返回null])。现在,在此代码中,您可能不会期待其他异常,但A)您可以稍后更改,B)RuntimeException可以在任何时候发生。最习惯使用该模式。

答案 1 :(得分:1)

这是一个品味问题 - 没有正确答案。

就个人而言,我更喜欢一个try / catch块。如果我看到很多,我开始担心我的方法做得太多而且太大了。这表明可能是时候把它分解成更小的方法了。

以下是我编写该方法的方法:

public void save(Object object, File file) throws IOException
{

    BufferedWriter writer  = null;

    try {
    writer = new BufferedWriter(new FileWriter(file));

    Dictionary dictionary = (Dictionary) object;
    ArrayList<Card> cardList = dictionary.getCardList();
    for (Card card : cardList)
    {
        String line = card.getForeignWord() + " / " + card.getNativeWord();
        writer.write(line);
    }
    }
    finally
    {
        IOUtils.close(writer); 
    }    
}

我有一个IOUtils类,它将封装流,读者和编写器的正确关闭。你会一次又一次地写这段代码。我将它作为一个单行代码作为类中的静态方法 - 或者如果我不介意另一个依赖项,则使用Apache Commons IO Utils JAR。

答案 2 :(得分:1)

什么是好的取决于您的代码的目的。例如,第二个try / catch位于循环内,这意味着它将处理列表中的所有card,即使处理失败也是如此。如果对整个方法使用一个try/catch,则会更改此行为。如果算法允许,请使用一个try/catch

答案 3 :(得分:0)

使用try-catch,有更多'不要'而不是'做'我害怕......

本文件列出了其中一些:

http://today.java.net/article/2006/04/04/exception-handling-antipatterns

尽管如此,有一些事情在那里,我发现这很有趣:

http://www.wikijava.org/wiki/10_best_practices_with_Exceptions

答案 4 :(得分:0)

在I / O的特定情况下,我建议您查看一些常用的库,例如Guava和Jakarta commons。他们有一些很好的脚本来执行静默关闭。

E.g。 Commons IO IOUtils

这些可以清理你的代码

答案 5 :(得分:0)

我更喜欢写两个try块,一个用于finally,一个用于catch。由于它的编写方式,您不会将writter设置为null,也不必在关闭时检查null。唯一的问题是异常,而关闭会在处理时隐藏异常,但如果你想以不同的方式处理这两个异常,这只是一个问题。

public void save(Object object, File file) {
    try {
        BufferedWriter writter = new BufferedWriter(new FileWriter(file));
        try {
            Dictionary dictionary = (Dictionary)object; 
            ArrayList<Card> cardList = dictionary.getCardList();
            for (Card card: cardList) {
                String line = card.getForeignWord() + " / " + card.getNativeWord();
                writter.write(line);
            }
        } finally {
            writter.flush();
            writter.close();
        }
    } catch (IOException e) {
        e.printStackTrace(); //Or something more useful
    }
}