Java try、catch和finally的确切执行顺序是什么?

Java try、catch和finally的确切执行顺序是什么?,java,exception,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 fileHa

在这个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
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
有时甚至这种输出:

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
无论我得到第一、第二或第三个输出,似乎都是在每次执行过程中随机发生的。我发现这显然是在讨论同样的问题,但我仍然不明白为什么有时会得到输出1、2或3。如果我正确理解了这段代码,那么输出1应该是我每次得到的结果(异常发生)。我如何确保获得一致的输出1,或者能够判断何时获得输出1或何时获得输出1
是否要获得输出2或3?

问题是您正在将一些输出写入
系统.out
,而将一些输出写入
系统.err
。这些是独立的流,具有独立的缓冲。据我所知,冲洗它们的时间没有规定

其缺点是,在写入不同的流时,不能使用输出显示的顺序来确定调用
println()
的顺序。请注意,
System.out
的输出始终按预期顺序显示


至于执行顺序,首先执行
try
的主体。如果抛出异常,则执行相应的
catch
子句的主体。
finally
块始终在最后执行。

使用try-catch块处理异常的方法是,如果控件在catch块中遇到任何异常,它将进入try。但是控件每次执行时都会转到最后一个块。

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


由于我看不到您的代码中有任何错误(尽管您的
catch
段中多余的
返回;
有一点卡在我的craw中),因此我建议您将所有消息都写入stderr,然后查看消息顺序是否与您期望的更一致。

您的示例中有一个小故障,我将删除它。您正在写入System.out和System.err,并期望控制台正确同步这两个流。为了消除副作用,我只在这里使用一个流。

首先执行
尝试
块如果成功,最终将执行;如果
尝试
块失败,则执行
捕获
并最终执行
。无论发生什么,最终块都将执行

但是


如果调用
System.exit(0)
finally block not executed

,但理论上,顺序应该是输出1中所示的顺序,不是吗?@user13267-是的。指定了执行顺序,它对应于您期望的输出顺序。将所有内容都放在一个流中(例如,
System.out
),您应该每次都能看到预期的订单。或者,在每次写入每个输出流后,立即对其调用
flush()
。这也会修正输出在控制台上的显示顺序。我尝试了
System.out.flush()
System.err.flush()
,每次调用它们时,输出顺序都保持不变。但是,总是将所有内容写入
系统。out
似乎以正确的顺序显示everytime@user13267-调用
flush()
时,“输出顺序保持不变”是什么意思?您的意思是,您仍然偶尔会收到意外的输出订单吗?或者你的意思是输出总是以相同的顺序(从不改变)?最终块将执行可能发生的重复。我不同意调用System.exit()会发生什么?@Sunny是的,你是正确的,但我只讨论这种情况。如果调用System.exit(0),请尝试。或者使JVM退出或挂起(比如死锁)。否则-否。