try,catch和finally的执行顺序是什么?

时间:2013-07-26 06:14:34

标签: java exception

在这个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

以及我是否获得第一,第二或第三输出似乎在每次执行期间随机发生。我发现THIS POST显然是在谈论同样的问题,但我仍然不明白为什么我有时会得到输出1,2或3.如果我正确理解这段代码那么输出1应该是我每次都得到的(发生异常)。我如何确保始终获得输出1,或者能够告诉我什么时候输出输出1或什么时候输出 输出2或3?

5 个答案:

答案 0 :(得分:18)

问题是您要将一些输出写入System.out,一些输出写入System.err。这些是独立的流,具有独立的缓冲。据我所知,他们被冲洗的时间没有明确说明。

缺点是,当写入不同的流时,您无法使用输出显示的顺序来确定对println()的调用发生的顺序。请注意,System.out的输出始终按预期顺序显示。

就执行顺序而言,首先执行try的正文。如果它抛出异常,则执行相应catch子句的主体。 finally块始终最后执行。

答案 1 :(得分:3)

首先执行Try阻止,如果成功,最终将执行,如果try阻止失败,则catch将执行,finally执行。什么都会发生最终块将执行。

但是

如果你致电System.exit(0)最后阻止未执行

答案 2 :(得分:2)

使用try catch块进行异常处理的事情是控件将进入内部尝试,如果它将在catch块中获得任何异常。但是每次执行时控件都会进入最后一个块。

答案 3 :(得分:1)

您正在向stdout和stderr写入错误消息。它们具有不同的缓冲区,因此无法保证您看到的输出与您在两个输出流之间创建的输出顺序相同。

由于我在代码中看不到任何错误(尽管return;段中多余的catch卡在了我的抓取中,但我建议您将所有消息写入stderr ,并查看消息顺序是否与您期望的更符合。

答案 4 :(得分:1)

你的例子中有一个小问题我会删除。您正在写入System.out和System.err,并使控制台正确同步两个流。为了消除副作用,我只想在这里使用一个流。