try,catch和finally的执行顺序是什么?
在这个java代码中,
import java.io.IOException; public class Copy { public static void main(String[] args) { if (args.length != 2) { System.err.println("usage: java Copy srcFile dstFile"); return; } int fileHandleSrc = 0; int fileHandleDst = 1; try { fileHandleSrc = open(args[0]); fileHandleDst = create(args[1]); copy(fileHandleSrc, fileHandleDst); } catch (IOException ioe) { System.err.println("I/O error: " + ioe.getMessage()); return; } finally { close(fileHandleSrc); close(fileHandleDst); } } static int open(String filename) { return 1; // Assume that filename is mapped to integer. } static int create(String filename) { return 2; // Assume that filename is mapped to integer. } static void close(int fileHandle) { System.out.println("closing file: " + fileHandle); } static void copy(int fileHandleSrc, int fileHandleDst) throws IOException { System.out.println("copying file " + fileHandleSrc + " to file " + fileHandleDst); if (Math.random() < 0.5) throw new IOException("unable to copy file"); System.out.println("After exception"); } }
我期望的输出是
copying file 1 to file 2 I/O error: unable to copy file closing file: 1 closing file: 2
但是有时我会得到这个预期的输出,有时我会得到以下输出:
copying file 1 to file 2 closing file: 1 closing file: 2 I/O error: unable to copy file
有时甚至是这个输出:
I/O error: unable to copy file copying file 1 to file 2 closing file: 1 closing file: 2
我是否得到第一,第二或第三输出似乎在每次执行期间随机发生。 我发现这个POST显然是在谈论同样的问题,但我仍然不明白为什么我有时会得到输出1,2或3.如果我正确理解这段代码那么输出1应该是我每次都得到的(exception发生) )。 我如何确保始终获得输出1,或者能够告诉我何时获得输出1或何时获得输出2或3?
问题是您正在向System.out
编写一些输出,而将一些输出写入System.err
。 这些是独立的流,具有独立的缓冲。 据我所知,他们被冲洗的时间没有明确说明。
缺点是,当写入不同的流时,您不能使用输出显示的顺序来确定对println()
的调用发生的顺序。 请注意, System.out
的输出始终以预期的顺序显示。
就执行顺序而言,首先执行try
的主体。 如果它抛出exception,则执行适当的catch
子句的主体。 finally
块总是最后执行。
首先执行Try
块,如果成功,最终将执行,如果try
块失败,则catch
将执行并finally
执行。 什么都会发生最终块将执行。
但
如果调用System.exit(0)
最后阻止不执行
使用try catch块进行exception处理的事情是控件将进入内部尝试,如果它将在catch块中获得任何exception。 但是每次执行时控件都将进入最后一个块。
您正在将错误消息写入stdout和stderr。 它们具有不同的缓冲区,因此无法保证您看到的输出与您在两个输出流之间创建的输出顺序相同。
因为我在代码中看不到任何错误(虽然多余的return;
在你的catch
段中卡住了我的一点点),让我建议你把所有的消息写到stderr,看看消息顺序是否有点更符合你的期望。
你的例子中有一个小问题我会删除。 您正在写入System.out和System.err,并使控制台正确同步两个流。 为了消除副作用,我在这里只使用一个流。