是否优先使用嵌套的try / catch块?

时间:2022-03-07 22:20:09

One of the things that always bugs me about using Readers and Streams in Java is that the close() method can throw an exception. Since it's a good idea to put the close method in a finally block, that necessitates a bit of an awkward situation. I usually use this construction:

在Java中使用Readers和Streams总是让我感到困惑的一件事是close()方法可以抛出异常。因为将close方法放在finally块中是个好主意,这需要一些尴尬的情况。我通常使用这种结构:

FileReader fr = new FileReader("SomeFile.txt");
try {
    try {
        fr.read();
    } finally {
        fr.close();
    }
} catch(Exception e) {
    // Do exception handling
}

But I've also seen this construction:

但我也看到了这种结构:

FileReader fr = new FileReader("SomeFile.txt");
try {
    fr.read() 
} catch (Exception e) {
    // Do exception handling
} finally {
    try {
        fr.close();
    } catch (Exception e) {
        // Do exception handling
    }
}

I prefer the first construction because there's only one catch block and it just seems more elegant. Is there a reason to actually prefer the second or an alternate construction?

我更喜欢第一个结构,因为只有一个挡块,它看起来更优雅。是否有理由更喜欢第二种或替代结构?

UPDATE: Would it make a difference if I pointed out that both read and close only throw IOExceptions? So it seems likely to me that, if read fails, close will fail for the same reason.

更新:如果我指出read和close都只抛出IOExceptions会有所不同吗?所以在我看来,如果读取失败,关闭将因同样的原因而失败。

11 个解决方案

#1


6  

I would always go for the first example.

我总是会去寻找第一个例子。

If close were to throw an exception (in practice that will never happen for a FileReader), wouldn't the standard way of handling that be to throw an exception appropriate to the caller? The close exception almost certainly trumps any problem you had using the resource. The second method is probably more appropriate if your idea of exception handling is to call System.err.println.

如果close是抛出一个异常(在实践中,FileReader永远不会发生),那么标准的处理方式是不是要抛出一个适合调用者的异常?近似的例外几乎肯定胜过你使用资源的任何问题。如果你的异常处理的想法是调用System.err.println,第二种方法可能更合适。

There is an issue of how far exceptions should be thrown. ThreadDeath should always be rethrown, but any exception within finally would stop that. Similarly Error should throw further than RuntimeException and RuntimeException further than checked exceptions. If you really wanted to you could write code to follow these rules, and then abstract it with the "execute around" idiom.

存在一个问题,即应该抛出多少异常。应始终重新抛出ThreadDeath,但finally中的任何异常都会阻止它。类似地,Error应该比RuntimeException和RuntimeException更多地抛出异常,而不是检查异常。如果你真的想要,你可以编写代码来遵循这些规则,然后用“执行周期”成语来抽象它。

#2


26  

I'm afraid there's a big problem with the first example, which is that if an exception happens on or after the read, the finally block executes. So far so good. But what if the fr.close() then causes another exception to be thrown? This will "trump" the first exception (a bit like putting return in a finally block) and you will lose all information about what actually caused the problem to begin with.

我担心第一个例子存在一个大问题,即如果在读取或读取之后发生异常,则执行finally块。到现在为止还挺好。但是如果fr.close()然后引发另一个异常会怎么样呢?这将“胜过”第一个异常(有点像在finally块中返回)并且您将丢失有关实际导致问题开始的内容的所有信息。

Your finally block should use:

你的finally块应该使用:

IOUtil.closeSilently(fr);

where this utility method just does:

这个实用程序方法只是这样做:

public static void closeSilently(Closeable c) {
    try { c.close(); } catch (Exception e) {} 
} 

#3


3  

I prefer the second one. Why? If both read() and close() throw exceptions, one of them could be lost. In the first construction, the exception from close() overrides the exception from read(), while in the second one, the exception from close() is handled separately.

我更喜欢第二个。为什么?如果read()和close()都抛出异常,则其中一个可能会丢失。在第一个构造中,close()的异常会覆盖read()的异常,而在第二个构造中,close()的异常会单独处理。


As of Java 7, the try-with-resources construct makes this much simpler. To read without caring about exceptions:

从Java 7开始,try-with-resources构造使这更加简单。阅读时不关心例外情况:

try (FileReader fr = new FileReader("SomeFile.txt")) {
    fr.read();
    // no need to close since the try-with-resources statement closes it automatically
}

With exception handling:

有异常处理:

try (FileReader fr = new FileReader("SomeFile.txt")) {
    fr.read();
    // no need to close since the try-with-resources statement closes it automatically
} catch (IOException e) {
    // Do exception handling
    log(e);
    // If this catch block is run, the FileReader has already been closed.
    // The exception could have come from either read() or close();
    // if both threw exceptions (or if multiple resources were used and had to be closed)
    // then only one exception is thrown and the others are suppressed
    // but can still be retrieved:
    Throwable[] suppressed = e.getSuppressed(); // can be an empty array
    for (Throwable t : suppressed) {
        log(suppressed[t]);
    }
}

Only one try-catch is needed and all exceptions can be safely handled. You can still add a finally block if you like, but there is no need to close the resources.

只需要一个try-catch,所有异常都可以安全地处理。如果愿意,您仍然可以添加finally块,但不需要关闭资源。

#4


2  

If both read and close throw an exception, the exception from read will be hidden in option 1. So, the second option does more error handling.

如果读取和关闭都抛出异常,则读取的异常将隐藏在选项1中。因此,第二个选项会执行更多错误处理。

However, in most cases, the first option will still be preferred.

但是,在大多数情况下,第一个选项仍然是首选。

  1. In many cases, you can't deal with exceptions in the method they are generated, but you still must encapsulate the stream handling within that operation.
  2. 在许多情况下,您无法处理生成它们的方法中的异常,但您仍必须在该操作中封装流处理。
  3. Try adding a writer to the code and see how verbose the second approach gets.
  4. 尝试在代码中添加一个编写器,看看第二种方法的详细程度。

If you need to pass all the generated exceptions, it can be done.

如果需要传递所有生成的异常,则可以完成。

#5


1  

The difference, as far as I can see, is that there are different exceptions and causes in play on different levels, and the

据我所知,差异在于,在不同的层面上有不同的例外和原因

catch (Exception e)

catch(例外e)

obscures that. The only point of the multiple levels is to distinguish your exceptions, and what you'll do about them:

掩盖了这一点。多个级别的唯一要点是区分您的异常,以及您将对它们做些什么:

try
{
  try{
   ...
  }
   catch(IOException e)
  {
  ..
  }
}
catch(Exception e)
{
  // we could read, but now something else is broken 
  ...
}

#6


1  

I usually do the following. First, define a template-method based class to deal with the try/catch mess

我通常会做以下事情。首先,定义一个基于模板方法的类来处理try / catch混乱

import java.io.Closeable;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public abstract class AutoFileCloser {
    private static final Closeable NEW_FILE = new Closeable() {
        public void close() throws IOException {
            // do nothing
        }
    };

    // the core action code that the implementer wants to run
    protected abstract void doWork() throws Throwable;

    // track a list of closeable thingies to close when finished
    private List<Closeable> closeables_ = new LinkedList<Closeable>();

    // mark a new file
    protected void newFile() {
        closeables_.add(0, NEW_FILE);
    }

    // give the implementer a way to track things to close
    // assumes this is called in order for nested closeables,
    // inner-most to outer-most
    protected void watch(Closeable closeable) {
        closeables_.add(0, closeable);
    }

    public AutoFileCloser() {
        // a variable to track a "meaningful" exception, in case
        // a close() throws an exception
        Throwable pending = null;

        try {
            doWork(); // do the real work

        } catch (Throwable throwable) {
            pending = throwable;

        } finally {
            // close the watched streams
            boolean skip = false;
            for (Closeable closeable : closeables_) {
                if (closeable == NEW_FILE) {
                    skip = false;
                } else  if (!skip && closeable != null) {
                    try {
                        closeable.close();
                        // don't try to re-close nested closeables
                        skip = true;
                    } catch (Throwable throwable) {
                        if (pending == null) {
                            pending = throwable;
                        }
                    }
                }
            }

            // if we had a pending exception, rethrow it
            // this is necessary b/c the close can throw an
            // exception, which would remove the pending
            // status of any exception thrown in the try block
            if (pending != null) {
                if (pending instanceof RuntimeException) {
                    throw (RuntimeException) pending;
                } else {
                    throw new RuntimeException(pending);
                }
            }
        }
    }
}

Note the "pending" exception -- this takes care of the case where an exception thrown during close would mask an exception we might really care about.

注意“挂起”异常 - 这将处理在关闭期间抛出的异常将掩盖我们可能真正关心的异常的情况。

The finally tries to close from the outside of any decorated stream first, so if you had a BufferedWriter wrapping a FileWriter, we try to close the BuffereredWriter first, and if that fails, still try to close the FileWriter itself.

最后尝试从任何装饰流的外部关闭,所以如果你有一个包装FileWriter的BufferedWriter,我们首先尝试关闭BuffereredWriter,如果失败,仍然尝试关闭FileWriter本身。

You can use the above class as follows:

您可以按如下方式使用上述类:

try {
    // ...

    new AutoFileCloser() {
        @Override protected void doWork() throws Throwable {
            // declare variables for the readers and "watch" them
            FileReader fileReader = null;
            BufferedReader bufferedReader = null;
            watch(fileReader = new FileReader("somefile"));
            watch(bufferedReader = new BufferedReader(fileReader));

            // ... do something with bufferedReader

            // if you need more than one reader or writer
            newFile(); // puts a flag in the 
            FileWriter fileWriter = null;
            BufferedWriter bufferedWriter = null;
            watch(fileWriter = new FileWriter("someOtherFile"));
            watch(bufferedWriter = new BufferedWriter(fileWriter));

            // ... do something with bufferedWriter
        }
    };

    // .. other logic, maybe more AutoFileClosers

} catch (RuntimeException e) {
    // report or log the exception
}

Using this approach you never have to worry about the try/catch/finally to deal with closing files again.

使用这种方法,您永远不必担心try / catch / finally再次处理关闭文件。

If this is too heavy for your use, at least think about following the try/catch and the "pending" variable approach it uses.

如果这对你的使用太重,至少要考虑遵循try / catch和它使用的“待定”变量方法。

#7


0  

The standard convention I use is that you must not let exceptions escape a finally block.

我使用的标准约定是你不能让异常转义为finally块。

This is because if an exception is already propagating the exception thrown out of the finally block will trump the original exception (and thus be lost).

这是因为如果异常已经传播,则从finally块抛出的异常将胜过原始异常(因此会丢失)。

In 99% of cases this is not what you want as the original exception is probably the source of your problem (any secondary exceptions may be side effects from the first but will obscure your ability to find the source of the original exception and thus the real problem).

在99%的情况下,这不是您想要的,因为原始异常可能是您的问题的根源(任何次要异常可能是第一个的副作用,但会模糊您找到原始异常的来源的能力,因此真实问题)。

So your basic code should look like this:

所以你的基本代码应如下所示:

try
{
    // Code
}
// Exception handling
finally
{
    // Exception handling that is garanteed not to throw.
    try
    {
         // Exception handling that may throw.
    }
    // Optional Exception handling that should not throw
    finally()
    {}
}

#8


0  

2nd approach.

第二种方法。

Otherwise, I don't see you catching the exception from the FileReader constructor

否则,我没有看到你从FileReader构造函数中捕获异常

http://java.sun.com/j2se/1.5.0/docs/api/java/io/FileReader.html#FileReader(java.lang.String)

http://java.sun.com/j2se/1.5.0/docs/api/java/io/FileReader.html#FileReader(java.lang.String)

public FileReader(String fileName) throws FileNotFoundException

public FileReader(String fileName)抛出FileNotFoundException

So, I usually have the constructor inside the try block as well. the finally block checks to see if the reader is NOT null before trying to do a close.

所以,我通常也在try块中有构造函数。在尝试关闭之前,finally块检查读取器是否为null。

The same pattern goes for Datasource, Connection, Statement, ResultSet.

Datasource,Connection,Statement,ResultSet使用相同的模式。

#9


0  

Sometimes nested try-catch is not a preference, consider this:

有时嵌套的try-catch不是首选项,请考虑以下情况:

try{
 string s = File.Open("myfile").ReadToEnd(); // my file has a bunch of numbers
 // I want to get a total of the numbers 
 int total = 0;
 foreach(string line in s.split("\r\n")){
   try{ 
     total += int.Parse(line); 
   } catch{}
 }
catch{}

This is probably a bad example, but there are times you will need nested try-cactch.

这可能是一个不好的例子,但有时你需要嵌套的try-cactch。

#10


0  

I like the approach by @Chris Marshall, but I never like to see exceptions getting swallowed silently. I think its best to log exceptions, especially if you are contiuing regardless.

我喜欢@Chris Marshall的方法,但我从不喜欢看到异常被静默吞噬。我认为最好记录异常,特别是如果你不管怎样。

I always use a utility class to handle these sort of common exceptions, but I would make this tiny different to his answer.

我总是使用实用程序类来处理这些常见的异常,但我会将这与他的答案完全不同。

I would always use a logger (log4j for me) to log errors etc.

我总是会使用记录器(对我来说是log4j)来记录错误等。

IOUtil.close(fr);

A slight modification to the utility method:

对实用方法略有修改:

public static void close(Closeable c) {
    try {
      c.close();
    } catch (Exception e) {
      logger.error("An error occurred while closing. Continuing regardless", e); 
    } 
}

#11


0  

In some cases a nested Try-Catch is unavoidable. For instance when the error recovery code itself can throw and exception. But in order to improve the readability of the code you can always extract the nested block into a method of its own. Check out this blog post for more examples on nested Try-Catch-Finally blocks.

在某些情况下,嵌套的Try-Catch是不可避免的。例如,当错误恢复代码本身可以抛出异常时。但是为了提高代码的可读性,您始终可以将嵌套块提取到自己的方法中。查看此博客文章,了解有关嵌套Try-Catch-Finally块的更多示例。

#1


6  

I would always go for the first example.

我总是会去寻找第一个例子。

If close were to throw an exception (in practice that will never happen for a FileReader), wouldn't the standard way of handling that be to throw an exception appropriate to the caller? The close exception almost certainly trumps any problem you had using the resource. The second method is probably more appropriate if your idea of exception handling is to call System.err.println.

如果close是抛出一个异常(在实践中,FileReader永远不会发生),那么标准的处理方式是不是要抛出一个适合调用者的异常?近似的例外几乎肯定胜过你使用资源的任何问题。如果你的异常处理的想法是调用System.err.println,第二种方法可能更合适。

There is an issue of how far exceptions should be thrown. ThreadDeath should always be rethrown, but any exception within finally would stop that. Similarly Error should throw further than RuntimeException and RuntimeException further than checked exceptions. If you really wanted to you could write code to follow these rules, and then abstract it with the "execute around" idiom.

存在一个问题,即应该抛出多少异常。应始终重新抛出ThreadDeath,但finally中的任何异常都会阻止它。类似地,Error应该比RuntimeException和RuntimeException更多地抛出异常,而不是检查异常。如果你真的想要,你可以编写代码来遵循这些规则,然后用“执行周期”成语来抽象它。

#2


26  

I'm afraid there's a big problem with the first example, which is that if an exception happens on or after the read, the finally block executes. So far so good. But what if the fr.close() then causes another exception to be thrown? This will "trump" the first exception (a bit like putting return in a finally block) and you will lose all information about what actually caused the problem to begin with.

我担心第一个例子存在一个大问题,即如果在读取或读取之后发生异常,则执行finally块。到现在为止还挺好。但是如果fr.close()然后引发另一个异常会怎么样呢?这将“胜过”第一个异常(有点像在finally块中返回)并且您将丢失有关实际导致问题开始的内容的所有信息。

Your finally block should use:

你的finally块应该使用:

IOUtil.closeSilently(fr);

where this utility method just does:

这个实用程序方法只是这样做:

public static void closeSilently(Closeable c) {
    try { c.close(); } catch (Exception e) {} 
} 

#3


3  

I prefer the second one. Why? If both read() and close() throw exceptions, one of them could be lost. In the first construction, the exception from close() overrides the exception from read(), while in the second one, the exception from close() is handled separately.

我更喜欢第二个。为什么?如果read()和close()都抛出异常,则其中一个可能会丢失。在第一个构造中,close()的异常会覆盖read()的异常,而在第二个构造中,close()的异常会单独处理。


As of Java 7, the try-with-resources construct makes this much simpler. To read without caring about exceptions:

从Java 7开始,try-with-resources构造使这更加简单。阅读时不关心例外情况:

try (FileReader fr = new FileReader("SomeFile.txt")) {
    fr.read();
    // no need to close since the try-with-resources statement closes it automatically
}

With exception handling:

有异常处理:

try (FileReader fr = new FileReader("SomeFile.txt")) {
    fr.read();
    // no need to close since the try-with-resources statement closes it automatically
} catch (IOException e) {
    // Do exception handling
    log(e);
    // If this catch block is run, the FileReader has already been closed.
    // The exception could have come from either read() or close();
    // if both threw exceptions (or if multiple resources were used and had to be closed)
    // then only one exception is thrown and the others are suppressed
    // but can still be retrieved:
    Throwable[] suppressed = e.getSuppressed(); // can be an empty array
    for (Throwable t : suppressed) {
        log(suppressed[t]);
    }
}

Only one try-catch is needed and all exceptions can be safely handled. You can still add a finally block if you like, but there is no need to close the resources.

只需要一个try-catch,所有异常都可以安全地处理。如果愿意,您仍然可以添加finally块,但不需要关闭资源。

#4


2  

If both read and close throw an exception, the exception from read will be hidden in option 1. So, the second option does more error handling.

如果读取和关闭都抛出异常,则读取的异常将隐藏在选项1中。因此,第二个选项会执行更多错误处理。

However, in most cases, the first option will still be preferred.

但是,在大多数情况下,第一个选项仍然是首选。

  1. In many cases, you can't deal with exceptions in the method they are generated, but you still must encapsulate the stream handling within that operation.
  2. 在许多情况下,您无法处理生成它们的方法中的异常,但您仍必须在该操作中封装流处理。
  3. Try adding a writer to the code and see how verbose the second approach gets.
  4. 尝试在代码中添加一个编写器,看看第二种方法的详细程度。

If you need to pass all the generated exceptions, it can be done.

如果需要传递所有生成的异常,则可以完成。

#5


1  

The difference, as far as I can see, is that there are different exceptions and causes in play on different levels, and the

据我所知,差异在于,在不同的层面上有不同的例外和原因

catch (Exception e)

catch(例外e)

obscures that. The only point of the multiple levels is to distinguish your exceptions, and what you'll do about them:

掩盖了这一点。多个级别的唯一要点是区分您的异常,以及您将对它们做些什么:

try
{
  try{
   ...
  }
   catch(IOException e)
  {
  ..
  }
}
catch(Exception e)
{
  // we could read, but now something else is broken 
  ...
}

#6


1  

I usually do the following. First, define a template-method based class to deal with the try/catch mess

我通常会做以下事情。首先,定义一个基于模板方法的类来处理try / catch混乱

import java.io.Closeable;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

public abstract class AutoFileCloser {
    private static final Closeable NEW_FILE = new Closeable() {
        public void close() throws IOException {
            // do nothing
        }
    };

    // the core action code that the implementer wants to run
    protected abstract void doWork() throws Throwable;

    // track a list of closeable thingies to close when finished
    private List<Closeable> closeables_ = new LinkedList<Closeable>();

    // mark a new file
    protected void newFile() {
        closeables_.add(0, NEW_FILE);
    }

    // give the implementer a way to track things to close
    // assumes this is called in order for nested closeables,
    // inner-most to outer-most
    protected void watch(Closeable closeable) {
        closeables_.add(0, closeable);
    }

    public AutoFileCloser() {
        // a variable to track a "meaningful" exception, in case
        // a close() throws an exception
        Throwable pending = null;

        try {
            doWork(); // do the real work

        } catch (Throwable throwable) {
            pending = throwable;

        } finally {
            // close the watched streams
            boolean skip = false;
            for (Closeable closeable : closeables_) {
                if (closeable == NEW_FILE) {
                    skip = false;
                } else  if (!skip && closeable != null) {
                    try {
                        closeable.close();
                        // don't try to re-close nested closeables
                        skip = true;
                    } catch (Throwable throwable) {
                        if (pending == null) {
                            pending = throwable;
                        }
                    }
                }
            }

            // if we had a pending exception, rethrow it
            // this is necessary b/c the close can throw an
            // exception, which would remove the pending
            // status of any exception thrown in the try block
            if (pending != null) {
                if (pending instanceof RuntimeException) {
                    throw (RuntimeException) pending;
                } else {
                    throw new RuntimeException(pending);
                }
            }
        }
    }
}

Note the "pending" exception -- this takes care of the case where an exception thrown during close would mask an exception we might really care about.

注意“挂起”异常 - 这将处理在关闭期间抛出的异常将掩盖我们可能真正关心的异常的情况。

The finally tries to close from the outside of any decorated stream first, so if you had a BufferedWriter wrapping a FileWriter, we try to close the BuffereredWriter first, and if that fails, still try to close the FileWriter itself.

最后尝试从任何装饰流的外部关闭,所以如果你有一个包装FileWriter的BufferedWriter,我们首先尝试关闭BuffereredWriter,如果失败,仍然尝试关闭FileWriter本身。

You can use the above class as follows:

您可以按如下方式使用上述类:

try {
    // ...

    new AutoFileCloser() {
        @Override protected void doWork() throws Throwable {
            // declare variables for the readers and "watch" them
            FileReader fileReader = null;
            BufferedReader bufferedReader = null;
            watch(fileReader = new FileReader("somefile"));
            watch(bufferedReader = new BufferedReader(fileReader));

            // ... do something with bufferedReader

            // if you need more than one reader or writer
            newFile(); // puts a flag in the 
            FileWriter fileWriter = null;
            BufferedWriter bufferedWriter = null;
            watch(fileWriter = new FileWriter("someOtherFile"));
            watch(bufferedWriter = new BufferedWriter(fileWriter));

            // ... do something with bufferedWriter
        }
    };

    // .. other logic, maybe more AutoFileClosers

} catch (RuntimeException e) {
    // report or log the exception
}

Using this approach you never have to worry about the try/catch/finally to deal with closing files again.

使用这种方法,您永远不必担心try / catch / finally再次处理关闭文件。

If this is too heavy for your use, at least think about following the try/catch and the "pending" variable approach it uses.

如果这对你的使用太重,至少要考虑遵循try / catch和它使用的“待定”变量方法。

#7


0  

The standard convention I use is that you must not let exceptions escape a finally block.

我使用的标准约定是你不能让异常转义为finally块。

This is because if an exception is already propagating the exception thrown out of the finally block will trump the original exception (and thus be lost).

这是因为如果异常已经传播,则从finally块抛出的异常将胜过原始异常(因此会丢失)。

In 99% of cases this is not what you want as the original exception is probably the source of your problem (any secondary exceptions may be side effects from the first but will obscure your ability to find the source of the original exception and thus the real problem).

在99%的情况下,这不是您想要的,因为原始异常可能是您的问题的根源(任何次要异常可能是第一个的副作用,但会模糊您找到原始异常的来源的能力,因此真实问题)。

So your basic code should look like this:

所以你的基本代码应如下所示:

try
{
    // Code
}
// Exception handling
finally
{
    // Exception handling that is garanteed not to throw.
    try
    {
         // Exception handling that may throw.
    }
    // Optional Exception handling that should not throw
    finally()
    {}
}

#8


0  

2nd approach.

第二种方法。

Otherwise, I don't see you catching the exception from the FileReader constructor

否则,我没有看到你从FileReader构造函数中捕获异常

http://java.sun.com/j2se/1.5.0/docs/api/java/io/FileReader.html#FileReader(java.lang.String)

http://java.sun.com/j2se/1.5.0/docs/api/java/io/FileReader.html#FileReader(java.lang.String)

public FileReader(String fileName) throws FileNotFoundException

public FileReader(String fileName)抛出FileNotFoundException

So, I usually have the constructor inside the try block as well. the finally block checks to see if the reader is NOT null before trying to do a close.

所以,我通常也在try块中有构造函数。在尝试关闭之前,finally块检查读取器是否为null。

The same pattern goes for Datasource, Connection, Statement, ResultSet.

Datasource,Connection,Statement,ResultSet使用相同的模式。

#9


0  

Sometimes nested try-catch is not a preference, consider this:

有时嵌套的try-catch不是首选项,请考虑以下情况:

try{
 string s = File.Open("myfile").ReadToEnd(); // my file has a bunch of numbers
 // I want to get a total of the numbers 
 int total = 0;
 foreach(string line in s.split("\r\n")){
   try{ 
     total += int.Parse(line); 
   } catch{}
 }
catch{}

This is probably a bad example, but there are times you will need nested try-cactch.

这可能是一个不好的例子,但有时你需要嵌套的try-cactch。

#10


0  

I like the approach by @Chris Marshall, but I never like to see exceptions getting swallowed silently. I think its best to log exceptions, especially if you are contiuing regardless.

我喜欢@Chris Marshall的方法,但我从不喜欢看到异常被静默吞噬。我认为最好记录异常,特别是如果你不管怎样。

I always use a utility class to handle these sort of common exceptions, but I would make this tiny different to his answer.

我总是使用实用程序类来处理这些常见的异常,但我会将这与他的答案完全不同。

I would always use a logger (log4j for me) to log errors etc.

我总是会使用记录器(对我来说是log4j)来记录错误等。

IOUtil.close(fr);

A slight modification to the utility method:

对实用方法略有修改:

public static void close(Closeable c) {
    try {
      c.close();
    } catch (Exception e) {
      logger.error("An error occurred while closing. Continuing regardless", e); 
    } 
}

#11


0  

In some cases a nested Try-Catch is unavoidable. For instance when the error recovery code itself can throw and exception. But in order to improve the readability of the code you can always extract the nested block into a method of its own. Check out this blog post for more examples on nested Try-Catch-Finally blocks.

在某些情况下,嵌套的Try-Catch是不可避免的。例如,当错误恢复代码本身可以抛出异常时。但是为了提高代码的可读性,您始终可以将嵌套块提取到自己的方法中。查看此博客文章,了解有关嵌套Try-Catch-Finally块的更多示例。